多继承及潜在问题
对象的继承,指的是一个子类对象获得父类对象的所有属性和方法,并且可以在此基础上拓展新的属性和方法的一种行为(个人理解,请勿当真。。)
那么继承可以一直进行,比如c继承自b,b又继承自a,那么c的父类是b,b的父类是a,c的爷类是a,这好理解
但是值得注意的是,c++可以支持多继承
这意味着
- 一个类可以有多个爹(父类)
- 爹类(父类)们,可能拥有共同的父类
- 那么一个类可能会拥有多个爷类,这时候就会发生冲突,因为爷类是同一个(即如下图的a)
这个时候就会发生问题,因为继承的特性是:子类先创建父类的对象,在创建子类自己的属性,那么会创建两个爷类对象,可是实际生产生活中一般只用一个爷类对象就够了,这可能有些抽象,所以举个例子:
- 有一个animal动物类,animal类有age年龄属性
- cat类和dog类继承自animal类
- 出现了新物种:catdog,catdog类继承自cat类和dog类(多继承)
按照继承特性,继承自cat和dog,cat和dog都会创建一个animal对象,所以catdog类有两个animal对象,那么catdog拥有两个年龄属性
可是客观描述和实际编程,年龄都是唯一的变量,这就造成了冲突和客观描述上的矛盾,而且造成了不必要的内存开销
更致命的是,同名的age变量更容易造成冲突与bug
如下的代码揭示了这种不合理的情况(即创建两个animal对象)
#include <bits/stdc++.h>
using namespace std;
class animal
{
public:
int age;
animal(){cout<<"animal对象被创建"<<endl;}
};
class cat : public animal
{
public:
int c;
cat(){cout<<"cat对象被创建"<<endl;}
};
class dog : public animal
{
public:
int d;
dog(){cout<<"dog对象被创建"<<endl;}
};
class catdog : public cat, public dog
{
public:
int cd;
catdog(){cout<<"catdog对象被创建"<<endl;}
};
int main()
{
catdog cd;
return 0;
}
解决方案:虚继承
因为继承的特性,子类在创建的时候,会先创建父类,所以上述问题会有两个爷类的情况出现,而我们需要消灭一个爷
虚拟继承的解决方法,是使得多继承的时候,某个公共基类的成员在其派生类(子类)中只产生一个拷贝
实现方法:virtual
关键字
cat类和dog类在继承基类animal的时候,加上virtual关键字,就会使得在后续的多继承中,如果catdog类的父类cat和dog都继承自animal,那么只会产生一个animal对象而不是两个
代码
#include <bits/stdc++.h>
using namespace std;
class animal
{
public:
int age;
animal(){cout<<"animal对象被创建"<<endl;}
};
// 继承基类时加上 virtual 关键字
class cat : virtual public animal
{
public:
int c;
cat(){cout<<"cat对象被创建"<<endl;}
};
// 继承基类时加上 virtual 关键字
class dog : virtual public animal
{
public:
int d;
dog(){cout<<"dog对象被创建"<<endl;}
};
class catdog : public cat, public dog
{
public:
int cd;
catdog(){cout<<"catdog对象被创建"<<endl;}
};
int main()
{
catdog cd;
return 0;
}