문제

멤버 함수 포인터를 사용하여 가상 함수의 기본 클래스 구현을 호출하고 싶습니다.

class Base {
public:
    virtual void func() { cout << "base" << endl; }
};

class Derived: public Base {
public:
    void func() { cout << "derived" << endl; }

    void callFunc()
    {
        void (Base::*fp)() = &Base::func;
        (this->*fp)(); // Derived::func will be called.
                       // In my application I store the pointer for later use,  
                       // so I can't simply do Base::func().
    }
};

위의 코드에서 func의 파생 클래스 구현은 callFunc에서 호출됩니다.Base::func를 가리키는 멤버 함수 포인터를 저장할 수 있는 방법이 있습니까? 아니면 이를 사용해야 합니까? using 어떤 면에서는?

내 실제 응용 프로그램에서는 Boost::bind를 사용하여 callFunc에 Boost::function 객체를 생성하고 나중에 내 프로그램의 다른 부분에서 func를 호출하는 데 사용합니다.따라서 Boost::bind 또는 Boost::function이 이 문제를 해결하는 방법이 있다면 도움이 될 것입니다.

도움이 되었습니까?

해결책

참조 또는 포인터를 통해 가상 메소드를 호출하면 항상 가장 파생 된 유형을 찾는 가상 통화 메커니즘을 활성화합니다.

가장 좋은 방법은 가상이 아닌 대체 기능을 추가하는 것입니다.

다른 팁

불행히도 당신이하는 일은 불가능합니다. 포인터 투 선원 기능입니다 설계 기능의 가상을 유지합니다.

문제는 멤버 함수 포인터가 기본 함수 포인터와 완전히 동일하지 않다는 것입니다.실제로는 단순한 포인터가 아니라 훨씬 더 복잡한 구조, 이는 컴파일러 구현 수준에서 세부 사항이 다릅니다.구문을 통해 호출하면 (this->*fp)() 실제로 원래 객체에서 호출하고 있으며 이로 인해 가상 함수 디스패치가 발생합니다.

작동할 수 있는 한 가지 방법은 메서드가 아닌 포인터 유형으로 캐스팅하는 것입니다.좀 삐걱거리긴 하지만 난 생각하다 작동해야합니다.당신은 여전히 ​​​​통과해야 Base * 그러나 이를 명시적으로 수행하면 가상 함수 디스패치가 우회됩니다.

typedef void BasePointer(Base*);

void callFunc()
{
    BasePointer fp = (BasePointer *)&Base::func;
    fp(this);
}

업데이트: 알았어, 아니, 그렇게 하면 안 돼.불법이고, 합법이라면 안전하지 않을 것입니다.그만큼 C++ FAQ 가지다 이것에 대해 더 자세히.그러나 그것을 아는 것만으로는 문제가 해결되지 않습니다.문제는 호출하려는 경우 객체에 대한 포인터 또는 멤버에 대한 포인터라는 것입니다. Base::func 통해 Base 포인터가 가리키는 개체는 다음과 같아야 합니다. 또한 가 되다 Base.이를 정렬할 수 있으면 멤버 함수 포인터를 사용할 수 있습니다.

예쁘지는 않지만 적어도 실행 가능한 또 다른 생각이 있습니다.에서 기능을 제공하세요. Derived, 비가상, 명시적으로 호출 Base::func.대신에 그것을 지적하십시오.다양한 변형이 있는 일반적인 경우에 이 작업을 수행해야 하는 경우 확장되지 않습니다. func 그리고 callFunc 하지만 한 가지 방법으로는 잘 작동합니다.

함수 포인터를 통해이 작업을 수행 할 특정 이유가 있습니까?

당신은 그냥 쓸 수 있어야합니다.

Base::func();

기본 클래스 구현을 호출합니다.

Quark의 말 외에도 더 일반적인 언급은 베어 함수 포인터가 아닌 신호/슬롯 구현을 사용해야한다는 것입니다. 부스트에는 하나가 있습니다. libsigc와 다른 많은 사람들이 있습니다.

이것에 무슨 문제가 있습니까?

(Base(*this).*fp)();

이제 만족한다면 왜 기능 포인터를 사용하고 있는지에 대한 의문이 제기됩니다. 더 많은 맥락이 도움이 될 것이라고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top