不同的行为:直接调用函数与通过非静态成员指针调用函数

Different Behaviour: Calling Function Directly vs. Through non-static member pointer

本文关键字:调用 函数 指针 静态成员      更新时间:2023-10-16

问题:

虽然我知道函数指针,但我不明白是什么让这两个函数在Derived类中有不同的作用:

I( StartPrintThroughFuncPtr()

II( StartPrint()

这是完整代码,加上注释中的输出

#include "iostream"
class Base
{
    (void)(Base::*callee)(void);
    virtual void Print(){std::cout<<"Print: Base"<<std::endl;}
public:
    void StartPrintThroughFuncPtr(){
        callee = &Base::Print;
        (this->*callee)();
    }
    void StartPrint(){
        Base::Print();
    }
};
class Derived : public Base
{
    virtual void Print(){std::cout<<"Print: Derived"<<std::endl;}
};
void main()
{
    Base *basePtr = new Base;
    basePtr->StartPrintThroughFuncPtr();    //  ==> "Print: Base"
    basePtr->StartPrint();                  //  ==> "Print: Base"
    Derived *derivedPtr = new Derived;
    derivedPtr->StartPrintThroughFuncPtr(); //  ==> "Print: Derived"
    derivedPtr->StartPrint();               //  ==> "Print: Base"
}

感谢=(

指向虚拟函数的指针实际上在虚拟函数表中存储偏移量,而不是指向函数的直接指针。这就是为什么通过它调用是虚拟的。

指向成员函数的指针支持多态行为。当您创建一个指向虚拟函数的指针时,调用会被调度到基于调用该函数的对象的运行时类型的实现(在您的情况下,是basePtrderivedPtr(。作用域解析运算符在那里并不重要,因为指向虚拟函数的函数指针并没有完全定义目标。

C++11标准,第4.11.2节:类型为"cv T类型的B的成员的指针"的prvalue,其中B是类类型,可以转换为类型为"CVT类型的D的成员的指示器"的prvalue,其中D是B的派生类(第10条(,但是它引用基类成员,就好像它是派生类的成员一样(强调(

另一方面,StartPrint通过其范围解析操作符直接调用Base类中的实现。