在c++中的继承中,如果基类声明了一个函数为虚函数,那么在派生类中不用声明同名函数为虚函数(不需要加virtual)也可以实现该函数为虚函数。
派生类继承了基类的属性,同名函数被视为与基类具有相同属性的函数。
如果基类为纯虚函数的话,那么派生类中也不用声明为virtual函数,但是必须实现其纯虚函数。
纯虚函数就是在定义的时候这样做:
vitual func()=0;
这样做的意思是包含了纯虚函数的类不能够生成实例,这个类叫做抽象类,也就是说这个类只是包含一些接口定义。而不包括实现,这就要求它的子类必须重新定义纯虚函数的实现。而普通虚函数,子类可以选择重新定义或者不重新定义。
抽象类
带有纯虚函数的类称为抽象类。抽象类具有下述一些特点:
(1) 抽象类只能作为基类使用,其纯虚函数的实现由派生类给出;但派生类仍可不给出纯虚函数的定义,继续作为抽象类存在。
(2) 抽象类不能定义对象,一般将该类的构造函数说明为保护的访问控制权限。
(3) 可以声明一个抽象类的指针和引用。通过指针和引用,可以指向并访问派生类对象,进而访问派生类的成员,这种访问是具有多态特征的。
虚函数
这个例子中WindowB和WindowC不同时存在,这在实际应用中是常有的情况,为了节省内存。
class WindowA { public: virtual void Draw(){}; }; class WindowB:public WindowA { public: WindowB(){}; void Draw(); }; class WindowC:public WindowA { public: WindowC(){}; void Draw(); }; void WindowB::Draw() { 画一个圆; } void WindowC::Draw() { 画一个正方形; }当在定义WindowA时,不确定它的派生类WindowB和WindowC在Draw函数中要画什么,这时把Draw定义成虚函数,在派生类中具体实现。
说到这,读者会问:那我把Draw在WindowB和WindowC中写好,还会少写一个类WindowA。
是的,是少写了,如你所说,你会如此使用:
WindowB* b = new WindowB;
b->Draw(); //画个圆
delete b;
WindowC* c = new WindowC;
c->Draw(); //画个正方形
delete c;
我这里用指针实现,在上面的代码中,b和c是两个独立的对象的指针。但如果派生类不是一两个,而是几十个,几百个,那你该怎么办呢?在头文件中定义几百个变量?
非也,到时候用虚函数的作用了:
WindowA*<wbr>a = new WindowsB;</wbr>
a->Draw();<wbr><wbr></wbr></wbr> //画个圆,此处调用了WindowB中的Draw函数实现
if(a)
delete a; //new 出来的一定要delete
WindowA* a=new WindowC;
a->Draw(); //画个正方形,此处调用了WindowC中的Draw函数实现
if(a)
delete a;
在上面的代码中,a实现了一个中转变量的作用,只要是从WindowA派生的,我都能赋值给a,而b和c都是临时变量。再来多少个WindowA的派生类都没问题了,我只要在头文件中定义一个WindowA的指针变量就行了。
<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr>与其叫纯虚函数还不如叫抽象类,它只是声明一个函数但不实现它,让派生类去实现它,其实这也很好理解。



















<wbr><wbr><wbr> 如上代码,定义了一个交通工具类(Vehicle),类中有一函数可打印出交通工具的轮胎个数,但交通工具很多轮胎个数自然也就不确定,所以就把它定义为纯虚函数,也就是光定义函数名不去实现它,类Camion继承了Vehicle并实现了里面的代码,打印出有4个轮胎。Bike类也是一样。有一点须要注意一下,纯虚函数不能实化化,但可以声明指针。</wbr></wbr></wbr>