読者です 読者をやめる 読者になる 読者になる

メンバ関数ポインタは仮想関数を正しく呼び出せるか?

呼び出せる。

class A;
typedef void (A::*member_function)();

class A {
    int a;
public:
    virtual ~A(){}
    virtual void f() { printf("A::f\n"); }
    virtual void m() { printf("A::m\n"); }
    virtual void n() { printf("A::n\n"); }
    
    void execute(int functionIndex) {
        (this->*functionTable[functionIndex])();
    }
    
    void print() {
        int* dump = reinterpret_cast<int*>(functionTable);
        for (int i = 0; i < 6; ++i) {
            printf("%d\n", dump[i] );
        }
    }
private:
    static member_function functionTable[];
};

member_function A::functionTable[] = {
    &A::f,
    &A::m,
    &A::n,
};

class B : public A {
    int b;
public:
    virtual void f() { printf("B::f\n"); }
    virtual void m() { printf("B::m\n"); }
};

class C : public B {
    int c;
public:
    virtual void f() { printf("C::f\n"); }
};

int main()
{
    A* a = new A();
    
    a->execute(0);
    a->execute(1);
    a->execute(2);
    
    a->print();
    
    delete a;
    
    A* ac = new C();
    
    ac->execute(0);
    ac->execute(1);
    ac->execute(2);
    
    ac->print();
    
    delete ac;
}

結果は、

A::f
A::m
A::n
9
0
13
0
17
0
C::f
B::m
A::n
9
0
13
0
17
0

functionTableには&A::fと書いてあるが、ちゃんとCのインスタンスからはC::fが呼び出せている。
念のため、両方functionTableをprintしているが、
勿論、functionTableはAのstaticメンバなので、
内容に違いはない。
member_functionのsizeofの結果が8になるが、
オフセットと、恐らくは何かが入る。
何かとか何か?、って感じなんだが通常は気にする必要はない筈だ。