多继承
多继承就是存在两个以及两个以上父类
-
权限问题和构造函数和单继承一样的,因为上一章(c++继承和派生)已经讲完,所以这里就不再过多赘述了
多继承的写法:
class A{
};
class B{
};
class C:继承方式 类名 , 继承方式 类名{
};
在继承多个父类时,我们需要用逗号隔开
//第一个父类
class Father
{
public:
Father(string FFName) :FFName(FFName) {}
protected:
string FFName;
};
//第二个父类
class Monther
{
public:
Monther(string MFName) :MFName(MFName) {}
protected:
string MFName;
};
//子类继承两个父类
class Son :public Father, public Monther
{
public:
Son(string FFName, string MFName, string SSName) :Father(FFName), Monther(MFName)
//要注意初始化父类只能用初始化参数列表!!
{
this->SFName = FFName + MFName;
this->SSName = SSName;
}
void print()
{
cout << FFName << endl; //Father的姓
cout << MFName << endl; //Mother的姓
cout << this->SFName + this->SSName << endl;
}
protected:
string SFName;
string SSName;
};
int main()
{
Son son("李", "田", "大牛");
son.print();
/*
打印结果:
李
田
李田大牛
*/
return 0;
}
到目前,我们可以发现,继承和类的组合有一些相似地方,我们把父类作为子类的数据成员也可以实现上述操作,不过继承多了继承的方式
虚继承
菱形继承是因为多继承存在问题而衍生的继承方式(菱形继承就是虚继承)
(题目可能会出现,但是自己写代码不会出现)
这里我们需要认识一个新的东西,virtual 是一个新的关键字,具体内容会在虚函数中讲到
这里B和C来继承A的时候,我们是需要虚继承的,否则会出现二义性问题
class A
{
public:
A(int a) :a(a) {}
int a = 666;
};
class B : public A
{
public:
B(int a) :A(a) {}
};
class C : public A
{
public:
C(int a) :A(a) {}
};
class D :public C, public B
{
public:
D(int a) : C(14), B(12) {}
void print()
{
cout << "A:" << " " << A::a << endl;
cout << "B:" << " " << B::a << endl;
cout << "C:" << " " << C::a << endl;
}
};
int main()
{
D dobject(23);
dobject.print();
/*
打印结果:
A: 14
B: 12
C: 14
*/
return 0;
}
从打印结果来看,似乎A,B,C中的a值都不同,此时A中的a是和C中的a一致,但是代码中,B和C都对其父类(A类)进行了初始化,A中a却和C中的a一致,这里是继承顺序问题导致的,如果继承顺序改变,A中的a值就会等于B中的a的值。这就是虚继承的二义性。
当我们进行虚继承的时候就可以发现D类中的构造函数出现了报错的问题,这就是最上面我们说的,进行虚继承的时候,孙子类需要调用祖父类的构造函数
这样构造函数就写对了,此时A,B,C中的a都是同一个值,也就是传进来的参数a,前面调用的B和C的构造函数就会失效
虚继承我们自身会很少去写这样的代码,不过他会出现在考题中, 我们只需要去搞清楚它的继承方式即可,并且知道直接继承会导致的问题,会改正问题