1.为什么构造函数不能是虚函数?
答:首先,我们要了解虚函数表vtable和虚函数指针vptr,vtable是for类的,vptr是for对象的,是在构造函数被调用时才初始化,对象里虚函数的调用都是依赖于vptr,如果有地方调用构造函数,一定发生在对象生成之前,这个时候连vptr都还没有初始化呢,哪能够调用虚函数。本身就是一个矛盾的命题。
2.虚函数是什么?多态有什么用?
答:这2个问题本身就是一个问题,多态是通过虚函数来实现的。
多态到底有用在做什么呢?这也不是一两句话可以概述。一些教程上都是通过类图来表示,我自己是这样理解的:在面向对象编程中,针对数据进行抽象和继承,构成一定的类层次。例如类B和类C继承自类A类,如果我们需要类B则写针对类B的代码,需要类C则写针对类C的代码,如果我们有100个派生类,就意味要写很多代码,我们每增加一个类,就必须通知使用者,增加了类层次和使用者之间的耦合度,这样使得代码复用性差,不够灵活。
而多态很好的解决了这一困境,例如如下代码:
class A
{
virtual void foo();
};
class B : public A
{
virtual void foo();
}
void fun(A* a)
{
a->foo();
}
在fun这个函数里,无论我传A或B还是C类型对象,foo方法都可以被正确的执行,产生不同的效果。这种同一个代码产生不同效果的特点,我把它叫做“多态”。这样就不需要写n个类的代码了,只需要用基类指针指向就可以了,从而提高了代码复用性。
就其根本是因为虚函数调用的时候,能够在运行时动态绑定该函数(这里不多描述动态绑定),这是由编译器来完成的工作,相当于它帮我们完成了类型识别,这么好的事情何乐而不为呢。
无论我从类A再继承多少个派生类,我不需要关心它是什么类别,我的fun函数不用修改,从而提高了代码的可复用性和可扩展性。