1. 继承
1.1 继承和派生的关系
基类和派生类的关系就是,派生类从基类派生而来。
1.2 派生语法
//派生语法
class Fish
{
//...
};
class Tuna:public Fish
{
//...
};
1.3 访问限定符protected
- 如果将成员用protected来修饰,则protected成员可以被该类的派生类和友元类访问。但是继承层次之外无法访问protected成员(如main()函数中)。
- public修饰的成员是对外公开的,类外可以随意访问公开成员。
- private修饰的成员只有类内作用域下才可以访问,类外和派生类都无法访问。
1.4 向基类传递参数(带参数基类构造函数的继承)
这种情况实际上就是用重载的、有参的基类构造函数,通过初始化列表来写派生类的构造函数。
//包含初始化列表的派生类构造函数
class Base
{
public:
Base(int num)
{
//...
}
};
class Derived:public Base
{
public:
Derived():Base(25)
{
//... 派生类的构造函数
}
};
1.5 派生类覆盖基类的方法
//派生类覆盖基类中的方法
class Base
{
public:
void function(int num)
{
//...实现代码
}
};
class Derived:public Base
{
public:
void function(int num)
{
//...实现代码
}
};
1.6 调用基类中被覆盖的方法
//调用基类中被覆盖的方法
Derived Myobj; //派生类
Myobj.Base::function(); //派生类t通过作用域调用基类的方法
1.7 派生类中隐藏基类的方法
派生类中实现了基类的同名方法时,基类的方法会被隐藏,基类的重载方法无法被调用。派生类对象只能使用派生类中实现的方法。
//在派生类中隐藏基类的方法
class Fish
{
public:
void Swim()
{
//...
}
void Swim(bool SomeParameter)
{
//...
}
};
class Tuna:public Fish
{
public:
void Swim()
{
//...
}
};
int main()
{
Tuna myDinner;
//myDinner.Swim(false) //错误,该方法属于基类,但已经被派生类隐藏
myDinner.Swim();
return 0;
}
1.9 构造顺序
实例化一个派生类对象时,构造顺序如下:
- 构造基类对象
- 构造派生类对象
1.10 析构顺序
实例化和析构一个派生类对象时,构造和析构顺序如下:
(实例化基类的成员对象,如果有)
1.构造基类
(实例化派生类的成员对象,如果有)
2.构造派生类
3.析构派生类
(析构派生类的成员对象,如果有)
4.析构基类
(析构基类的成员对象,如果有)
2. 私有继承
私有继承的意思是派生类的实例中,基类的所有公有成员和方法都是私有的(不能从外部访问)。也就是说,即使是基类的公有成员和方法,也只能被派生类使用,而无法通过派生类的实例使用。
简而言之,在继承层次结构之外(包括main函数等),派生类对象无法访问基类的公有成员
//私有继承
class Derived:private Base
3. 保护继承
保护继承和私有继承的类似之处有:
- 私有继承和保护继承都表示has-a的关系
- 保护继承的派生类也可以访问基类的公有和保护成员
- 在继承层次结构之外(包括main函数等),无法访问基类的公有成员
不同之处在于:
- 保护继承下,子类的子类可以访问基类的公有成员。换做私有继承时,只能到子类,继承层次只有一层。
//保护继承
class Derived:protected Base
组合或者聚合
实际上只有在必要时,才使用私有或保护继承。否则容易成为架构上的性能评瓶颈。
聚合:奖基类对象作为派生类的成员属性,避免复杂情况的架构瓶颈。
4. 切除问题
在定义一个基类对象时,如果使用子类对象来初始化基类,则新定义的基类对象只包含基类部分,子类部分将被切除。
5. 多继承
多继承的意思是一个子类由多个基类同时派生而来,语法如下:
//多继承类的声明语法
class Derived:public classA, public classB, public classC
{
//...
};