よく、あなたは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
私はあなたができるとは思いません。しかし、私は過去に間違っていました:)私より知識のある人が道を知ってくれることを祈りましょう。 –
これは 'p-> :: foo();'のように直接呼び出すことができますが、メンバ関数へのポインタは使用できません(これは仮想関数のポイントです)。 –
私は、これを回避するには、作業を行うバーチャルではない 'bar'を使用し、' foo'を 'bar'に委譲すると、' callBase'は 'bar'を呼び出します。これはより多義です。多態性とは 'B'が常に' foo'を呼び出すということです。 –