2017-12-26 18 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のコンストラクタ内のフィールドに2番目のポインタを格納する必要があります。ここで

はコードです:

#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

仮想メソッドは仮想メソッドに多型とポインタを実装するように設計されている彼らの多型の行動をサポートしています。しかし、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() 
関連する問題