早就想写下这篇文章了,太懒了一直没写。一是想记下一些知识点,巩固下,再者希望通过写博,让自己更加对软件开发感兴趣,打发寂寞。可是水平有限,只能自娱自乐。
c++虚函数和虚继承可以说是c++最重要的语言特性了。虚函数实现了多态,虚继承避免了多继承情况下的出错。
先来说一下虚函数。还是给个小例子吧。
class Base
{
virtualvoid print(){ std::cout<<”Base”<<endl; }
};
class Derive:public Base
{
virtual void print(){ std::cout<<”Derive”<<endl;}
};
当定义一个Derive对象,Base指针指向这个对象时,用指针或者基类引用去访问print函数,调用的是派生类函数,这就实现了多态。为什么必须用指针和引用?
只要有虚函数,每个类都会有一个虚函数表,类中的指针都指向这个虚函数表,而这个虚函数表只有在运行时,才能确定它的地址,指针和引用能实现动态编译,故不能用基类对象赋值为派生类对象访问派生类虚函数实现动态编译,当定义一个基类对象并赋值为派生类对象时,是静态编译,当访问print函数,对象只会找自己的虚函数。也即硬编码。
而当改成私有继承时,编译会出错,因为c++不允许私有继承的派生类赋值给基类对象或指针。
下面再来说一下多继承,写得都很浅。
也给一个例子。
class Base1
{
voidprint();
};
class Base21:public Base1
{
}
class Base31:public Base2
{
}
clasee Derive:public Base21,public Base31
{
}
这就是多继承,Derive分别从Base21和Base31继承了两次Base1,这样增加了内存,很多时候并不是用户所希望的,所以可以如下把Base1声明为虚基类,这样,Derive就只拥有一份Base1内存。
class Base21:public virual Base1
{
}
class Base31:public virtual Base2
{
}
还有个问题,为什么我们总是把基类的析构函数声明为虚析构函数?
通过上面的分析,可能已经有了答案,当一个Base类指针去删除一个Derive对象时,如果析构函数不是虚析构函数,由于硬编码Base只会调用自己的析构函数,派生类函数没有调用到。我想我们都知道这样对程序会带来危害。