一、继承
1.定义
继承机制时面向程序设计使代码可以复用的最重要是手段,它允许程序员在保持原有类特性的基础上进行扩展,这样产生的类就称子类或者派生类。
继承基类成员访问方式的变化
类成员/继承方式 | public继承 | protected继承 | private继承 |
---|---|---|---|
基类的public成员 | 派生类的public成员 | 派生类的protected成员 | 派生类的private成员 |
基类的protected成员 | 派生类的protected成员 | 派生类的protected成员 | 派生类的private成员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
(1)基类的私有成员不可访问,基类的其它成员在子类的访问方式==Min(成员在基类的访问限定符,继承方式),public>protected>private
(2)不可见 是指:内存上,子类对象有这个成员,但是语法规定不能访问
(3)class默认是私有访问,struct默认为共有访问
二、基类与派生类对象赋值转换
1.派生类对象可以赋值给基类的对象/基类的指针/基类的引用,也叫切片或切割,意为把派生类中父类那部分切来赋值过去
2.基类对象不能赋值给派生类对象
3.基类的指针可以通过强制类型转换赋值给派生类的指针,但必须是基类的指针是指向派生类对象时才是安全的。
基类如果是多态类型,可以使用RTT的dynamic cast来进行识别后进行安全转换
三、继承中的作用域
1.在继承体系中,基类和派生类都有独立的作用域
2.子类和父类有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这叫隐藏也叫重定义(在子类成员函数中,可以使用 基类::基类成员 显示访问)
3.如果是成员函数的隐藏,只需要函数名相同就构成隐藏
4.实际中,最好不要定义同名的成员
四、派生类的默认成员
友元关系不能继承,即基类友元不能访问子类私有和保护成员
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一
个static成员实例 。
七、多继承
单继承:一个子类只有一个直接父类
多继承:一个子类有两个或两个以上直接父类
菱形继承:
导致:
(1)数据冗余
(2)二义性:指定访问冗余成员的作用域
解决方法:虚继承(在“腰部”添加virtual)
C++编译器如何通过虚继承如何解决数据冗余和二义性?
1.通过监视窗口已经看不到真实的存在,因为监视窗口被编译器处理过
2.建议使用内存窗口来进行查看
虚基表
虚继承是为了补多继承带来的菱形继承的坑,但代码也大
1.对象模型更复杂
2.一定效率影响
软件设计类之间关系或者模块间关系强调:高内聚、低耦合(继承)is-a关系
继承的类之间是一种强关联关系(B与A之间是一种强关联关系)
class A
{
public:
void func(){}
protected:
int _a;
};
//B继承了A,可以复用A
class B : public A
{
protected:
int _b;
};
白箱复用
B里面既可以用A的公有成员,也可以用保护成员,A所有成员对于B都是透明的,随便用。关联度高,A的改变,基本上都会影响B
A的封装对B是不太起作用的
类里面的成员之间关联度很高,类和类之间关联度很低(组合)has-a关系
组合的类与类之间是一种弱关联关系(C与A之间是一种弱关联关系)
class A
{
public:
void func(){}
protected:
int _a;
};
//C继承了A,可以复用A
class C : public A
{
private:
int _c;
A _a;
};
黑箱复用
C里面只能用A共有的成员,A的私有成员对C是不透明的,C与A的关联度低,A的改变对C很小,A的封装对B是起作用的