2017-12-26 5 views
6

포인터로 파생 클래스에서 기본 메서드 A :: foo()를 호출해야합니다.파생 클래스의 함수 포인터로 기본 가상 메서드 호출

#include <iostream> 
struct A{ 
    virtual void foo() { std::cout << "A::foo()" << std::endl; } 
}; 

struct B:A{ 
    virtual void foo() { std::cout << "B::foo()" << std::endl; } 
    void callBase(void (A::*f)()){ 
     (this->*f)(); 
    } 
}; 

int main(){ 
    B* p=new B(); 
    p->callBase(&A::foo); 
} 

이 코드는 "B :: foo"를 출력합니다. 메서드를 가리키는 포인터로 A :: foo()를 호출 할 수 있습니까?

+0

나는 당신이 할 수 있다고 생각하지 않습니다. 그러나, 나는 과거에 잘못되었습니다 :) 나보다 지식이 많은 사람이 길을 알고 있기를 바랍니다. –

+1

'p-> :: foo();와 같이 직접 호출 할 수는 있지만 멤버 함수에 대한 포인터는 아닙니다 (가상 함수의 포인트라고 생각합니다). –

+0

저는이 작업을 수행하는 가상이 아닌'bar'를 사용하고'foo' 대리자를'bar'에 위임함으로써이 문제를 해결할 것이라고 믿습니다.'callBase'는'bar'를 호출합니다. 다형성은'B'가 항상 자신의'foo'를 호출해야 함을 의미하므로 더 논리적입니다. –

답변

1

음, this의 값을 덮어 쓰면서 몇 가지 트릭을 사용하여 비슷한 작업을 수행 할 수 있습니다. 당신은 아마 그렇게하려고 시도해서는 안되며, vtable 포인터는 수작업으로 수정 될 의도가 없습니다.

설명 된대로하려면 A의 vtable에 대한 포인터가 있어야합니다. 객체 p에는 B의 vtable에 대한 포인터 만 있으므로 A의 생성자 내의 필드에 두 번째 포인터를 저장해야합니다.

#include <iostream> 
struct A{ 
    virtual void foo() { std::cout << "A::foo()" << std::endl; } 
    int *a_vtable_ptr; 
    // First, save value of A's vtable pointer in a separate variable. 
    A() { a_vtable_ptr = *(int**)this; } 
}; 

struct B:A{ 
    virtual void foo() { std::cout << "B::foo()" << std::endl; } 
    void callBase(void (A::*f)()){ 
     int *my_vtable_ptr = *(int**)this; 
     // Then modify vtable pointer of given object to one that corresponds to class A. 
     *(int**)this = a_vtable_ptr; 
     (this->*f)(); // Call the method as usual. 
     // Restore the original vtable pointer. 
     *(int**)this = my_vtable_ptr; 
    } 
}; 

// Function main() is not modified. 
int main(){ 
    B* p=new B(); 
    void (A::*f)() = &A::foo; 
    p->callBase(f); 
} 

출력 :

A::foo() 

Process finished with exit code 0 
1

가상 방법은 가상 메소드로 다형성 및 포인터를 구현하도록 설계되어 자신의 다형성 (polymorphic)를 지원 여기

는 코드입니다. 그러나 명시 적으로 p->A::foo()을 호출하여 기본 메서드를 호출 할 수 있습니다.

포인터로 기본 메서드를 호출하려면 가상으로 만들지 않아야합니다 (주석에서 언급 한 @PasserBy).

코드 예제 :

struct A { 
    virtual void foo() { std::cout << "A::foo()" << std::endl; } 
    void bar() { std::cout << "A::bar()" << std::endl; } 
    void callBase(void (A::*f)()) { (this->*f)(); } 
}; 

struct B : A { 
    virtual void foo() { std::cout << "B::foo()" << std::endl; } 
    void bar() { std::cout << "B::bar()" << std::endl; } 
}; 

int main() 
{ 
    A* p = new B(); 
    p->foo(); 
    p->bar(); 
    p->callBase(&A::foo); 
    p->callBase(&A::bar); 
    p->A::foo(); 
    p->A::bar(); 
} 

는 출력 :

B::foo() 
A::bar() 
B::foo() 
A::bar() 
A::foo() 
A::bar() 
관련 문제