多继承
- C++中有两种继承:单一继承和多重继承。(java 只有单继承)
- 对于单继承,派生类只能有一个基类;
对于多继承,派生类可以有多个基类。
定义
一个类从多个基类派生的一般形式:
class 类名1:访问控制 类名2, 访问控制 类名3, ... , 访问控制 类名n
{ ...//定义派生类自己的成员 };
- 多继承可以视为单继承的扩展。
构造函数
派生类名::派生类名(基类形参, 本类形参): 基类名1(参数), 基类名2(参数), ...基类名n(参数)
{
本类成员初始化赋值语句;
};
有内嵌对象时的构造函数
派生类名::派生类名(基类1形参, 基类2形参, ... 基类n形参,本类形参):基类名1(参数), ... ,基类名n(参数)
{
本类成员初始化赋值语句;
};
构造函数的调用次序
- 调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)。
- 调用成员对象的构造函数,调用顺序按照它们在类中声明的顺序。
- 派生类的构造函数体中的内容。
#include <iostream>
using namespace std;
class A
{private:
int a;
public:
void setA( int x ){a=x;};
void showA( ){cout <<"a="<< a << endl; }
};
class B
{private:
int b;
public:
void setB( int x ) { b = x; }
void showB ( ) { cout << "b="<< b << endl; }
};
class C : public A, private B
//2个基类,多继承
{ private:
int c;
public:
void setC(int x, int y ){c=x; setB(y);}
void showC( )
{showB( );
cout << "c="<<c << endl;}
};
int main( )
{ C obj;
obj.setA(53);//a=53
obj.setC(55,58);// b=58 c=55
obj.showA( ); //输出a=53
obj.showC(); //输出b=58 c=55
return 0;
}
- 类C从类A公有派生,因此类A公有成员在C中仍是公有(保护)。类C从类B私有派生,类B的所有成员在类C中是私有的。
- 这些成员在派生类中的可访问性和单一继承中一致。
- 类B被私有继承,因此,类C还需要负责维护类B数据成员值和显示,所以在showC和setC中分别调用类B成员函数showB和setB。使用obj.setB() 和 obj.showB()都是错误的。
多继承中的同名覆盖问题
-
同名覆盖
在多继承中,一个派生类的多个基类具有同名成员,如果派生类也声明了同名成员,派生类的成员覆盖多个基类中的同名成员。 -
域作用域
派生类对象d要想访问基类中的同名成员,就必须使用域作用符“::”。使用规则如下: - 基类名::成员名; //数据成员 - 基类名::函数名(参数); //函数成员 - 作用就是指明要访问的是哪个类中的同名成员。
-
当派生类与基类中有相同成员时:
- 若未强行指名,则通过派生类对象使用的是派生类中的同名成员。
- 如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定。
二义性问题
解决方法:
-
- 作用域分辨符
-
- 同名覆盖原则
-
- 虚函数
//多继承中的同名问题示例
#include <iostream>
using namespace std;
class B1
{public:
int num;
void