根据虚函数的不同位置,有着不同的作用。大致分为3类:虚拟继承,虚函数,纯虚函数
(1)虚拟继承
class A{
public:
int data;
};
class B : virtual public A
{
private:
int b;
};
class C : virtual public A
{
private:
int c;
};
class D : public C, public B
{
};
int main(int argc, char *argv[])
{
D d;
count<<d.data<<endl;
return 0;
}
像这样的多继承很容易产生二义性,如果用的不是虚拟继承,则cout<<d.data<<endl; 对象d的data值是继承于类C还是类B,不知道产生二义性。因为派生类D继承了类B类D,所以派生类里面即有来自类B的data,也有来自类C的data。但是如果用虚拟继承,则数据data在派生类D中只有一份,是直接从类A中拷贝过来的。
(2)虚函数
将成员函数设置为虚函数
class A{
public:
virtual void fun(){cout<<"A::fun"<<endl;}
};
class B : public A{
public:
void fun(){cout<<"B::fun()"<<endl;}
};
class C : public A{
public:
void fun(){cout<<"C::fun()"<<endl;}
};
int main()
{
B b;
C c;
A *p = &b;
A *p1 = &c;
p->fun();
p1->fun();
return 0;
}
编译结果:
B::fun()
C::fun()
可以看出利用虚函数可以实现多态,即实现了不同对象使用相同的接口实现了不同的功能。
虚函数这里还有个比较重要的知识点,将用于基类的析构函数设置虚函数的好处,在我的上篇博客中有总结。
(3)纯虚函数
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
virtual void funtion()=0;
纯虚函数的几个概念:
《1》带有纯虚函数的类为抽象类
《2》继承纯虚函数的类,且没有派生类没有对基类中的纯虚函数进行重写,则这个派生类也为抽象类。
《3》抽象类不能实例化对象
《4》派生类继承了纯虚函数,并且对纯虚函数的成员函数进行了重写,这个派生类就成为了具体类。
纯虚函数的作用:
-
为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
-
在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
纯虚函数是为你的程序制定一个标准,即只要你继承了我,就必须按照我的标准来,实现我所有的方法,否则你也是虚拟的,即为了提高代码的通用性,让所有继承它的子类全部按照同一标准来工作
class A{
public:
virtual void fun1() = 0;
virtual void fun2() = 0;
};
class B : public A{
public:
void fun1(){cout<<"B::fun1()"<<endl;}
void fun2(){cout<<"B::fun2()"<<endl;}
};
class C : public A{
public:
void fun1(){cout<<"C::fun1()"<<endl;}
void fun2(){cout<<"C::fun2()"<<endl;}
};
int main()
{
A *p1 = new B;
A *p2 = new C;
p1->fun1();
p2->fun2();
return 0;
}