继承的访问级别
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 49 课,共 104 课。
你选择的继承类型会影响派生类如何访问基类成员。C++ 提供三种选项:public、protected 和 private 继承。
下面介绍每种继承方式如何改变成员访问权限:
| 基类成员 | public 继承 | protected 继承 | private 继承 |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | 无法访问 | 无法访问 | 无法访问 |
class Base {
public:
int pub;
protected:
int prot;
private:
int priv;
};
class PublicDerived : public Base {
// pub 是公有的,prot 是受保护的,priv 无法访问
};
class ProtectedDerived : protected Base {
// pub 是受保护的,prot 是受保护的,priv 无法访问
};
class PrivateDerived : private Base {
// pub 是私有的,prot 是私有的,priv 无法访问
};公有继承用于表示“是一种”的关系,也是最常见的继承方式。Dog 是一种 Animal,因此外部代码可以将它当作 Animal 来处理。
受保护继承和私有继承表示“基于……实现”的关系。它们会向外部代码隐藏基类接口,适用于你想复用实现但不想公开继承关系的情况。使用私有继承时,进一步派生的类也无法访问原始基类成员。
挑战
简单让我们通过构建一个简单的设备层次结构,探索不同的继承类型如何影响成员的可访问性。你将创建一个基类 Device 和三个派生类,每个派生类使用一种不同的继承类型,以便亲自了解 public、protected 和 private 继承如何改变成员访问权限。
你将在两个文件中组织代码:
Device.h:定义基类Device,并在不同的访问级别下添加三个成员:- 一个 public 的
std::string model - 一个 protected 的
int serialNumber - 一个 private 的
int internalCode(默认设为 999) - 一个 public 方法
showModel(),用于打印:Model: <model>
然后创建三个派生类,每个类都使用不同的继承类型继承
Device:PublicDevice使用 public 继承:添加一个方法displaySerial(),用于打印:Serial: <serialNumber>ProtectedDevice使用 protected 继承:添加一个方法displaySerial(),用于打印:Serial: <serialNumber>PrivateDevice使用 private 继承:添加一个方法displaySerial(),用于打印:Serial: <serialNumber>
每个派生类都应有一个构造函数,接收设备型号和序列号,将型号传给基类,并设置序列号。
- 一个 public 的
main.cpp:读取两个输入(每个输入单独占一行):- 设备型号(字符串)
- 序列号(整数)
使用相同的输入值分别创建一个各派生类型的对象。然后展示访问权限上的差异:
对于
PublicDevice:- 直接对对象调用
showModel()(可以调用,因为 public 继承会保留其 public 访问权限) - 直接访问
model并打印:Direct model access: <model> - 调用
displaySerial()
对于
ProtectedDevice和PrivateDevice:- 只调用
displaySerial()(从外部无法再公开访问继承来的showModel()和model)
输出格式:
--- PublicDevice --- Model: <model> Direct model access: <model> Serial: <serial> --- ProtectedDevice --- Serial: <serial> --- PrivateDevice --- Serial: <serial>
例如,输入 Laptop 和 12345 时:
--- PublicDevice ---
Model: Laptop
Direct model access: Laptop
Serial: 12345
--- ProtectedDevice ---
Serial: 12345
--- PrivateDevice ---
Serial: 12345请注意,只有 PublicDevice 允许从外部访问继承来的 public 成员。其他继承类型会对外部代码隐藏基类接口,但派生类仍可在自己的方法中访问受保护成员。
亲手试试
#include <iostream>
#include <string>
#include "Device.h"
using namespace std;
int main() {
// 读取输入
string modelName;
int serialNum;
getline(cin, modelName);
cin >> serialNum;
// TODO:用输入值创建每种派生类型的对象
// PublicDevice pubDev(modelName, serialNum);
// ProtectedDevice protDev(modelName, serialNum);
// PrivateDevice privDev(modelName, serialNum);
// TODO:演示如何访问 PublicDevice
cout << "--- PublicDevice ---" << endl;
// 直接在对象上调用 showModel()
// 直接访问 model 并打印:Direct model access: <model>
// 调用 displaySerial()
// TODO:演示如何访问 ProtectedDevice
cout << "--- ProtectedDevice ---" << endl;
// 只调用 displaySerial()(无法从外部访问 showModel 和 model)
// TODO:演示如何访问 PrivateDevice
cout << "--- PrivateDevice ---" << endl;
// 只调用 displaySerial()(无法从外部访问 showModel 和 model)
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器