一.什么是多继承
二. 多继承下派生类的定义格式如下:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
class C: public A, public B
{
public:
};
其中,<继承方式1>,<继承方式2>,…是三种继承方式:public、private、protected之一。
三. 多继承的构造函数
在多继承的情况下,派生类的构造函数格式如下:
<派生类名>(<总参数表>):<基类名1>(<参数表1>),<基类名2>(<参数表2>),…
<子对象名>(<参数表n+1>),…
{
<派生类构造函数体>
}
其中,<总参数表>中各个参数包含了其后的各个分参数表。
四.派生类构造函数执行顺序
1.先执行所属基类的构造函数
2.再执行派生类本身构造函数
注:执行基类构造函数的顺序取决于定义派生类时基类的顺序
//代码1(代码1和代码2对比)
#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"A's constructor"<<endl;
}
};
class B
{
public:
B()
{
cout<<"B's constructor"<<endl;
}
};
class C: public A, public B//先A后B
{
public:
C()
{
cout<<"C's constructor"<<endl;
}
};
int main()
{
C c;
return 0;
}
//输出"A's constructor"然后是"B's constructor"最后是"C's constructor"
//代码2
#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"A's constructor"<<endl;
}
};
class B
{
public:
B()
{
cout<<"B's constructor"<<endl;
}
};
class C: public B, public A//先B后A
{
public:
C()
{
cout<<"C's constructor"<<endl;
}
};
int main()
{
C c;
return 0;
}
//先输出"B's constructor"再输出"A's constructor"最后输出"C's constructor"
#include<iostream>
using namespace std;
class A
{
int a;
public:
A(int x)
{
a=x;
cout<<"A's constructor"<<endl;
}
int geta()
{
return a;
}
};
class B
{
int b;
public: B(int y)
{
b=y;
cout<<"B's constructor"<<endl;
}
int getb()
{
return b;
}
};
class C: public A, public B
{
int c;
public:C(int x,int y,int z):B(x),A(y)
{
z=c;
cout<<"C's constructor"<<endl;
}
};
int main()
{
C c(1,2,3);
A a1(5);
cout<<c.geta()<<endl<<c.getb()<<endl;
cout<<a1.geta()<<endl;
cout<<c.geta();
return 0;
}
五. 二义性问题
-
第一种:
-
同名二义性:在继承时,基类之间、或基类与派生类之间发生成员同名时,将出现对成员访问的不确定性
//错误代码举例:
#include <iostream>
using namespace std;
class A
{
public:
void show()
{
cout<<"This is A";
}
};
class B
{
public:
void show()
{
cout<<"This is B";
}
};
class Son:public A,public B
{
public:
void display()
{
cout<<"This is son\n";
}
};
int main()
{
Son son;
son.show();//错误,因为不知道访问类A中的show(),还是访问类B中的show()
son.display();
cout << "Hello world!" << endl;
return 0;
}
-
解决方法一:利用作用域限定符::,用来限定派生类类调用的是哪个基类的show()函数
son.show() ===> son.A::show()或者son.B::show()
//正确代码举例:son.A::show()
#include <iostream>
using namespace std;
class A
{
public:
void show()
{
cout<<"This is A"<<endl;
}
};
class B
{
public:
void show()
{
cout<<"This is B"<<endl;
}
};
class Son:public A,public B
{
public:
void display()
{
cout<<"This is son"<<endl;
}
};
int main()
{
Son son;
son.A::show();
son.display();
cout << "Hello world!" << endl;
return 0;
}
-
解决方法二:在派生类中定义同名成员,覆盖掉基类中的相关成员
//正确代码举例:
#include <iostream>
using namespace std;
class A
{
public:
void show()
{
cout<<"This is A"<<endl;
}
};
class B
{
public:
void show()
{
cout<<"This is B"<<endl;
}
};
class Son:public A,public B
{
public:
void display()
{
cout<<"This is son"<<endl;
}
void show()
{
cout<<"show::This is son"<<endl;
}
};
int main()
{
Son son;
son.show();//此时son.show()将调用son.Son::show()
son.display();
cout << "Hello world!" << endl;
return 0;
}
-
第二种:
-
路径二义性: 有最基类A,有A的派生类B、C,又有D同时继承B、C,那么若A中有成员m,那么在派生类B,C中就存在m,又D继承了B,C,那么D中便同时存在B继承A的m和C继承A的m,那么当D的实例调用m的时候就不知道该调用B的m还是C的m,就导致了二义性。
//错误代码
#include <iostream>
using namespace std;
class A
{
public:
int m;
};
class B:public A {};
class C:public A {};
class D:public B,public C {};
int main()
{
D d;
d.m= 10;//错误,因为不知道调用B的m还是C的m
cout << "Hello world!" << endl;
return 0;
}
-
解决方法一:使用作用域限定符,指明访问的是哪一个基类的成员
d.m= 10 ====> d.B::m= 10或者d.C::m= 10
#include <iostream>
using namespace std;
class A
{
public:
int m;
};
class B:public A {};
class C:public A {};
class D:public B,public C {};
int main()
{
D d;
d.B::m= 10;
cout << "Hello world!" << endl;
return 0;
}
-
解决方法二:在派生类中D定义同名成员,覆盖掉父类中的相关成员
class A
{
public:
int m;
};
class B:public A {};
class C:public A {};
class D:public B,public C
{
public:
int m;
};
//正确代码举例
#include <iostream>
using namespace std;
class A
{
public:
int m;
};
class B:public A {};
class C:public A {};
class D:public B,public C
{
public:
int m;
};
int main()
{
D d;
d.m= 10;//此处相当于访问的D的m
cout<<d.D::m<<endl;
cout<<"Hello world!"<<endl;
return 0;
}
#include <iostream>
using namespace std;
class A
{
public:
int m;
};
class B:virtual public A {};
class C:virtual public A {};
class D:public B,public C
{
public:
int m;
};
int main()
{
D d;
d.m= 10;
cout<<"Hello world!"<<endl;
return 0;
}