【问题标题】:C++ Pointer to virtual functionC++ 指向虚函数的指针
【发布时间】:2011-10-08 22:44:43
【问题描述】:

如果你有这样的结构

struct A {
    void func();
};

还有一个像这样的参考

A& a;

您可以像这样获得指向其func 方法的指针:

someMethod(&A::func);

现在,如果该方法是虚拟的并且您在运行时不知道它是什么,该怎么办?为什么不能得到这样的指针?

someMethod(&a.func);

是否可以获得指向该方法的指针?

【问题讨论】:

    标签: c++ function-pointers virtual-functions member-function-pointers


    【解决方案1】:

    指向成员的指针考虑了它们所指向的函数的虚拟性。 例如:

    #include <iostream>
    struct Base
    {
        virtual void f() { std::cout << "Base::f()" << std::endl; }
    };
    
    struct Derived:Base
    {
        virtual void f() { std::cout << "Derived::f()" << std::endl; }
    };
    
    
    void SomeMethod(Base& object, void (Base::*ptr)())
    {
        (object.*ptr)();    
    }
    
    
    int main()
    {
        Base b;
        Derived d;
        Base* p = &b;
        SomeMethod(*p, &Base::f); //calls Base::f()
        p = &d;
        SomeMethod(*p, &Base::f); //calls Derived::f()    
    }
    

    输出:

    Base::f()
    Derived::f()
    

    【讨论】:

    • 谢谢!我没有意识到成员函数指针会考虑到这一点。
    • @Chris:成员函数指针很聪明。这就是为什么它们可以比通常的函数指针大。在多重继承的情况下,它们甚至会考虑基类子对象的偏移量
    【解决方案2】:

    调用函数指针的方法是同时提供其对象的实例指针。这将解决所有虚拟问题:

    struct A { void func(); };
    
    int main()
    {
      typedef void (A::*mf)();
    
      A x; // irrelevant if A is derived or if func is virtual
    
      mf f = &A::func;   // pointer-to-member-function
      A* p = &x;         // pointer-to-instance
    
      (p->*f)();           // invoke via pointer
      (x.*f)();            // invoke directly
    }
    

    好的,有趣的语法挑战问题:假设我有这个。

    struct Basil { virtual void foo(); virtual ~Basil(); };
    struct Derrek : public Basil { virtual void foo(); };
    

    现在如果我有Derrek * pBasil * p,我可以通过p-&gt;Basil::foo() 调用Basil 成员。如果给我void(Derrek::*q)() = &amp;Derrek::foo,我怎么能这样做?

    回答:这是不可能的。单独的PMFq不知道它是否指向一个虚函数,更不用说是哪个虚函数了,也不能用于在运行时查找基类函数。 [感谢史蒂夫和卢克!]

    【讨论】:

    • 我认为你的意思是 p->*f()。 (但现在说 func 是虚拟的,可以是 A::func 或 B::func - 你不知道它是什么。你怎么能得到一个指向正确的指针?)
    • 克里斯,我编辑了错字。在您最初的问题中,您不必担心,您将始终调用正确的多态函数。
    • @Chris,在底层,用于虚函数的成员函数指针包含一个 vtable 索引,而不是实际的函数指针。当调用函数指针时,编译器将在 vtable 中查找索引并调用相关函数。
    • 没错。如果x 是多态的,则通过PTMF 调用调用的机制与直接调用x.func() 所导致的机制完全相同,即在类的vtable 中查找func 的最派生位置。
    • "syntax challenge" 那么给定一个未知派生类成员函数的指针,你想调用基类的同名成员函数吗?我不认为你可以,虽然我可能是错的。关于p-&gt;Basil::foo() 的要点是您使用完全限定名称来引用Basil 的方法 - 仅给出一个您不知道函数名称的指针,因此您不能使用相同的名称完全限定名称中的符号。
    【解决方案3】:

    你可以得到一个指向它的指针,像这样:

    struct A {
        virtual void foo() = 0;
    };
    
    typedef void (A::*LPFOO)();
    
    LPFOO pFoo = &A::foo;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      相关资源
      最近更新 更多