Menu
CoddyTech

继承的访问级别

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 49 课,共 104 课。

你选择的继承类型会影响派生类如何访问基类成员。C++ 提供三种选项:public、protected 和 private 继承。

下面介绍每种继承方式如何改变成员访问权限:

基类成员public 继承protected 继承private 继承
publicpublicprotectedprivate
protectedprotectedprotectedprivate
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 来处理。

受保护继承和私有继承表示“基于……实现”的关系。它们会向外部代码隐藏基类接口,适用于你想复用实现但不想公开继承关系的情况。使用私有继承时,进一步派生的类也无法访问原始基类成员。

challenge icon

挑战

简单

让我们通过构建一个简单的设备层次结构,探索不同的继承类型如何影响成员的可访问性。你将创建一个基类 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>

    每个派生类都应有一个构造函数,接收设备型号和序列号,将型号传给基类,并设置序列号。

  • main.cpp:读取两个输入(每个输入单独占一行):
    1. 设备型号(字符串)
    2. 序列号(整数)

    使用相同的输入值分别创建一个各派生类型的对象。然后展示访问权限上的差异:

    对于 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;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器