一道C++多态的题目,考察多态和构造顺序的。求输出结果:
#include <iostream>
#include <vector>
class Base
{
public :
Base(){ cout<<"Base::Base()"<< endl; virt(); }
virtual void virt() { cout<<"Base::virt()"<< endl; }
void func(){ cout<<"Base::func()"<< endl; }
};
class Derived : public Base
{
public :
Derived(){ cout<<"Derived::Derived()"<< endl; virt(); }
virtual void virt() { cout<<"Derived::virt()"<< endl; }
void func() { cout<<"Derived::func()"<< endl; }
};
int main(){
Derived d;
Base *pb = & d;
pb-> func();
pb-> virt();
return 0 ;
}
#include <vector>
class Base
{
public :
Base(){ cout<<"Base::Base()"<< endl; virt(); }
virtual void virt() { cout<<"Base::virt()"<< endl; }
void func(){ cout<<"Base::func()"<< endl; }
};
class Derived : public Base
{
public :
Derived(){ cout<<"Derived::Derived()"<< endl; virt(); }
virtual void virt() { cout<<"Derived::virt()"<< endl; }
void func() { cout<<"Derived::func()"<< endl; }
};
int main(){
Derived d;
Base *pb = & d;
pb-> func();
pb-> virt();
return 0 ;
}
分析:
首先基类和派生类的函数分为两种,一种是虚函数,一种是非虚函数。
关于多态。那么两种函数的区别在于虚函数是动态绑定的,非虚函数是静态绑定的。基类指针pb的静态类型是Base,动态类型是Derived,那么调用静态绑定的函数当然是符合其静态类型。
关于构造顺序。无需多说,当然是先构造基类,然后构造派生类。
至于深层次的原因和虚函数virt()的调用,那需要《深入探索C++对象模型》。。。在基类的构造函数中调用virt(),因为此时派生类的对象还没开始构造呢,所以只有基类对象存在,因此调用virt()函数只能是调用基类的版本。但是当调用了派生类的构造函数之后,派生类的对象就存在了,这个时候再调用虚函数,将得到派生类的版本。
这是因为两条原则:
构造函数的函数体(或构造函数所调用的函数)能可靠地访问基类中声明的数据成员和/或构造函数所属类声明的数据成员。这是因为所有这些数据成员被保证在构造函数函数体开始执行时已经被完整的建立。
在基类的构造函数执行期间,对象还不是一个派生类的对象。
在基类的构造函数执行期间,对象还不是一个派生类的对象。
所以输出结果就是:
Base::Base()
Base::virt()
Derived::Derived()
Derived::virt()
Base::func()
Derived::virt()
Base::virt()
Derived::Derived()
Derived::virt()
Base::func()
Derived::virt()