1、继承类默认继承了基类的成员函数,即,在不重定义的前提下,y.f( )和y.X::f( )调用的同一个函数
而组合类则必须通过成员类对象进行函数调用,一个类的构造函数调用顺序是先基类,再组合类,最后会进行本类的构造函数。
2 如果重定义了基类的函数,则基类的同名函数全部自动隐藏。所谓“全部”是因为,可能在基类中有多个同名的重载函数,它们全部隐藏
覆盖是指派生类函数覆盖基类函数
函数名相同;
参数相同;
基类函数必须有Virtual关键字;
不同的范围(派生类和基类)。
隐藏是指派生类屏蔽了基类的同名函数相同
1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。
2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏
所谓“隐藏”不是说不能调用,而是说,当调用y.f( )时调用的是Y中定义的新f( ),想调用基类的f则要显式说明y.X::f( ),显式说明而已。
3 所有构造函数、析构函数、operator=都不能自动继承 ,但编译器会自动生成默认构造函数、拷贝构造函数、operator=,并正确地调用基类的相应函数,它们工作的很好
如果要为子类定义带参数的构造函数,则必须同时也定义子类的默认构造函数。如果自定义了拷贝构造函数,则也必须同时自定义默认构造函数
在子类的拷贝构造函数中,如果想调用基类的拷贝构造函数,必须显式在初始化列表调用,否则编译器自动调用默认构造函数
在子类的operator=中,如果想调用基类的operator=,必须显式在函数体中调用,否则编译器什么都不做。
#include <iostream>
using namespace std;
//继承问题!
class A
{
public:
A(int i = 0){cout<<"A is doing"<<endl;};
A(const A& i){cout<<"A Copy is doing"<<endl;};
void print(void)
{
cout<<"A cout"<<endl;
}
};
class B
{
public:
B(int i = 0){cout<<"B is doing"<<endl;};
B(const B& i){cout<<"B Copy is doing"<<endl;};
};
class C : public A //继承类
{
B b; //组合类
public:
//初始化语法:对于基类,使用类名调用构造函数;对于成员类,使用对象名调用构造函数
C(int i = 0):b(i), A(i) {cout<<"C is doing"<<endl;};
// C(int i = 0):A(i),b(i) {cout<<"C is doing"<<endl;};
// C(int i = 0):b(i) {cout<<"C is doing"<<endl;};
// C(int i = 0):A(i) {cout<<"C is doing"<<endl;};
// C(int i = 0) {cout<<"C is doing"<<endl;};
C(const C& i):A(i), b(i.b){cout<<"C Copy is doing"<<endl;};
//这地方要显式的调用基类的拷贝构造函数,否则编译器调用了基类的缺省构造函数!
//这地方如果不指明调用B的拷贝构造函数,编译器会调用B的不带参数的缺省构造,很明显!
void print(void)
{
cout<<"C cout"<<endl;
}
};
int main()
{
C c(2); //构造顺序是A B C
// c.A::print();
// c.C::print();
C d=c;
//d.A::print();
return 0;
}
这个程序有几个点:
1 首先,不管C类的构造函数怎么写,初始化列表或者怎么调用,怎么个顺序,各个类的构造顺序均不变,为A B C (基类, 组合类, 子类)
C(int i = 0):b(i), A(i) {cout<<"C is doing"<<endl;};
// C(int i = 0):A(i),b(i) {cout<<"C is doing"<<endl;};
// C(int i = 0):b(i) {cout<<"C is doing"<<endl;};
// C(int i = 0):A(i) {cout<<"C is doing"<<endl;};
// C(int i = 0) {cout<<"C is doing"<<endl;};
2,如果不显式的调用b的拷贝构造函数,编译器便会调用b的默认构造函数这很好理解,如果不显式调用A的拷贝构造函数,编译器将会调用A的默认构造函数!
3,如果A或者B没有自己定义的拷贝构造函数,C如果显式调用他们的拷贝构造调用的是编译器合成的拷贝构造函数。如果C没有定义拷贝构造函数,,编译器的合成拷贝构造函数会调用B的拷贝构造,因为编译器合成的拷贝构造是将内部成员依次拷贝。所以此时也会先调用A的拷贝构造,因为这个合成的拷贝构造函数会显式的调用它。