问题:
虽然我知道函数指针,但我无法理解是什么让这两个函数在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"
}
谢谢=)
答案 0 :(得分:3)
指向虚函数的指针实际上存储虚函数表中的偏移量,而不是指向函数的直接指针。这就是为什么通过它进行调用是虚拟的。
答案 1 :(得分:2)
指向成员函数的指针支持多态行为。当您创建指向虚函数的指针时,调用将调度到基于调用函数的对象的运行时类型的实现(在您的情况下,即basePtr
或{{1 }})。范围分辨率运算符在那里并不重要,因为指向虚函数的函数指针不能完全定义目标。
另一方面,C ++ 11标准,第4.11.2节:类型为“指向cv T类型B的成员的指针”的prvalue,其中B是类类型,可以转换为类型为“指向成员的指针”的prvalue类型为cv T“的D,其中D是B的派生类(第10节)。[...] 转换的结果是指与转换发生前指向成员的指针相同的成员,但是它将基类成员称为派生类的成员。(强调添加)
derivedPtr
通过其范围解析运算符直接调用StartPrint
类中的实现。