关于基类构造函数调用虚函数的问题
基类:
class Base{
Base(){ A();}
virtual void A(){cout<<"Base A"<<endl;};
}
派生类:
class Derived:public Base{
Derived(){}
void A(){cout<<"Derived A"<<endl;}
}
Base* pb=new Derived();
问现在调用的是基类中的A()还是派生类中的A()? 即打印Base A还是Derived A?
[解决办法]
Base(){ A();}//调用的是Base类中的,很简单,在这个构造函数里面只有基类部分构造好了。另外effective C++里面应该有说过,永远不要在构造函数里面调用虚函数。
[解决办法]
打印Base类中的A,因为在子类构造的时候首先构造父类的对象,不要再构造函数中调用虚函数
[解决办法]
是这样的
编译器在背后给你做了很多事情
Base* pb=new Derived();
后准备进入Derived的构造函数
这个时候编译器发现Derived有基类 并且有默认构造函数 所以在进入derived构造函数之前先进入Base的构造函数
在进入 Base的构造函数 的左大括号后
编译器首先 构造虚函数表 和 vptr
这个时候编译器在base里面操作 虚函数表里的地址都是base类 虚函数的入口地址
当虚函数表和vptr构造好后 继续执行程序员写在base构造函数里面的代码 一直到右括号 退出base构造函数 回到derived构造函数
同理
进入左大括号后
编译器发现vptr和 虚函数表已经建好
这个时候他做的就是 跟新虚函数表里面的地址 用 derived里面重写的虚函数的地址 刷新 原来的地址
做完后 继续执行 程序员写在derived构造函数里面 余下的代码
所以为什么base构造函数里面调用虚函数会是base 自己的了
这些都是因为编译器做了很多事没告诉你
[解决办法]
打印结果是
Base A
Derived A
Base* pb=new Derived(); // 调用基类的构造函数
前提是基类的构造函数是public的