在C++中,代码重用是通过继承(inheritance)机制实现的
所谓继承,就是在一个已经存在的类的基础上,再建立一个新类
从已有类派生出的新类,继承了原有类(基类)的特征,包括成员和方法
通过继承可以完成下面一些功能
- 可以在已有类的基础上添加一些新功能
- 可以给类添加数据成员
- 可以修改类方法的行为
继承是一个机制,只需提供新特性,甚至不需要访问源码,就可以派生出新类
继承的有点
积累定义公共内容,方便统一修改
- 提高代码的可重用性:类库(不需要了解核心技术的细节)
重定义基类的成员函数
添加新类,新成员更方便
注意
- 派生类对象存储了基类的数据成员,即派生类继承了基类的实现
- 派生类对象可以使用基类的非私有函数,即派生类继承了基类的接口
- 派生类需要自己的构造方法
- 派生类可以根据需要添加需要的额外数据成员和函数
公有继承
#include <iostream>
using namespace std;
// 基类
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// 派生类
class Rectangle: public Shape //public表示公有继承
{
public:
int getArea()
{
return (width * height);
}
};
int main(void)
{
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);
// 输出对象的面积
cout << "Total area: " << Rect.getArea() << endl;
return 0;
}
派生类如果不实现基类中的方法,默认会调用基类方法
派生类如果实现了基类方法(相当于覆盖了基类的实现)那么就会调用子类的实现
没有继承时,成员变量和成员函数会分开存储:
- 对象的内存中只包含成员变量,存储在栈区或堆区(使用new创建对象时)
- 成员函数与对象分离,存储在代码区
对象1-->成员变量1
对象2-->成员变量2
对象3-->成员变量3
编译器会将成员变量和成员函数分开存储,分别为每个对象的成员函数分配内存,但是所有对象都共享同一段函数代码
类可以看作是一种复杂的数据类型,当使用sizeof()函数求类所占空间大小,会发现,只计算了成员变量的大小,并没有把成员函数包含在内
有继承关系时,派生类的内存模型可以看成是基类成员变量和新增成员变量的总和
所有成员函数任然存储在另外一个区域–代码区,由所有对象共享
有关基类,派生类构造
- 实例化派生类对象时,首先会创建基类对象(调用基类构造)
- 派生类构造应通过成员初始化列表将基类信息传递给基类构造
- 应该在派生类构造中初始化派生类新增的数据成员
派生类对象可以使用基类的非私有成员函数
基类指针可以在不进行显式类型转换的情况下指向派生类对象(基类指针可以直接指向派生类对象)
不可以将基类对象和地址赋给派生类对象和地址,即不能做逆操作
可以将派生对象赋值给基类对象,程序将隐式重载赋值运算符
派生类成员的访问控制
基类成员/继承方式 | 公有继承 | 私有继承 | 保护继承 |
---|
公有(public) | 公有 | 私有 | 受保护 |
受保护(protected) | 受保护 | 私有 | 受保护 |
私有(private) | 不被继承 | 不被继承 | 不被继承 |