在C++FAQ上看到一个关于虚函数的重载说明,原贴内容如下:
[23.3] 当基类构造函数调用虚函数时,为什么不调用派生类重写的该虚函数?
当基类被构造时,对象还不是一个派生类的对象,所以如果 Base::Base()调用了虚函数 virt(),则 Base::virt() 将被调用,即使 Derived::virt()(译注:即派生类重写的虚函数)存在。
同样,当基类被析构时,对象已经不再是一个派生类对象了,所以如果 Base::~Base()调用了virt(),则 Base::virt()得到控制权,而不是重写的 Derived::virt() 。
当你可以想象到如果 Derived::virt() 涉及到派生类的某个成员对象将造成的灾难的时候,你很快就能看到这种方法的明智。详细来说,如果 Base::Base()调用了虚函数 virt(),这个规则使得 Base::virt()被调用。如果不按照这个规则,Derived::virt()将在派生对象的派生部分被构造之前被调用,此时属于派生对象的派生部分的某个成员对象还没有被构造,而 Derived::virt()却能够访问它。这将是灾难。
意思是说在C++中,如果基类的构造函数中调用它定义的的虚函数,即使在派生类中对这个虚函数进行了重写,实际运行中调用的仍是基类的版本。具体原因可以参见上面的说明,大概意思是在基类的构造函数中,子类对象还未被构造出来,所以这个时候调用的仍是基类的。
但是在C#中,同样的情况,基类中调用的却是派生类重写后的版本。我在本机是试过,运行结果是这样的,但是不是太明白为什么。