c++ 三种继承(public protect private)

本文详细解析了 C++ 中 public、protected 和 private 三种继承方式的特点与区别,包括它们在语义上的含义及语法上的表现形式,并讨论了它们是否符合 Liskov 替换原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要参考了下面的文章,根据它来谈谈自己的看法。

参考文章:http://blog.sina.com.cn/s/blog_60cc33d70100xylq.html

先贴张图:

1. public继承

    从语义角度上来说,public继承是一种接口继承(可以理解为子类对象可以调用父类的接口,也就有可能实现多态了)

  从语法角度上来说,public继承后,关系见上图。很明显父类public成员在子类中仍然是public,所以子类对象可以调用父类的接口

 

2. protected继承

  从语义角度上来说,protected继承是一种实现继承

   从语法角度上来说,protected继承后,父类public和protected成员都变成子类的protected成员了,也就是说子类对象无法调用父类的接口,只能将父类的函数当作子类的内部实现,当然也就不符合“Liskov替换原则(LSP”了。

 

3. private继承

   从语义角度上来说,private继承是一种实现继承

  从语法角度上来说,private继承后,父类public和protected成员都变成子类的private了,它比protected继承更严格。也就说这些父类的成员只能被继承一次,再继续继承,父类的成员就不可见了。private继承更不符合“Liskov替换原则(LSP”了。

 

  

<think>我们正在讨论C++中的protected访问权限在继承中的行为和使用场景。根据引用内容,我们可以总结如下:1.protected成员在类内部和派生类中可以被访问,但不能被类外部直接访问(引用1、5)。2.在继承时,根据继承方式的不同,基类成员的访问权限在派生类中会发生变化(引用2、3)。3.使用场景:当基类的成员需要被派生类访问,但又不希望被外部直接访问时,使用protected(引用1、5)。具体规则:-基类的protected成员在派生类中:-如果是public继承:在派生类中仍然是protected成员(可以被该派生类的成员函数访问,但不能被外部访问)。-如果是protected继承:基类的publicprotected成员在派生类中都变成protected成员(引用2)。-如果是private继承:基类的publicprotected成员在派生类中都变成private成员(引用2、3)。使用场景举例:-基类中定义了一些辅助函数,这些函数是为了给派生类使用的,而外部不需要知道这些函数的存在。这时可以将这些函数声明为protected(引用5)。-在构建类层次结构时,如果希望某些数据成员或成员函数能够被派生类使用,但又不希望被外部直接访问,就可以使用protected(引用1)。注意:实际开发中,public继承最常用,protected和private继承较少使用(引用3)。下面我们通过代码示例来说明:```cppclassBase{protected:intprotectedVar;voidprotectedFunc(){}public:intpublicVar;voidpublicFunc(){}};//public继承classDerivedPublic:publicBase{public:voiduseProtected(){protectedVar=1;//正确:可以访问基类的protected成员protectedFunc();//正确publicVar=2;//正确:public成员在派生类中仍然是public}};//protected继承classDerivedProtected:protectedBase{public:voiduseProtected(){protectedVar=1;//正确protectedFunc();//正确publicVar=2;//正确,但publicVar在派生类中变成了protected成员}};//private继承classDerivedPrivate:privateBase{public:voiduseProtected(){protectedVar=1;//正确protectedFunc();//正确publicVar=2;//正确,但publicVar在派生类中变成了private成员}};intmain(){DerivedPublicd1;d1.publicFunc();//正确:public继承,基类的public成员在派生类中仍然是public//d1.protectedFunc();//错误:protected成员不能在类外访问DerivedProtectedd2;//d2.publicFunc();//错误:protected继承后,基类的public成员在派生类中变成了protected,不能在类外访问DerivedPrivated3;//d3.publicFunc();//错误:private继承后,基类的public成员在派生类中变成了private,不能在类外访问}```在以上代码中:-在public继承中,基类的protected成员在派生类中仍然是protected,因此可以在派生类的成员函数中使用,但不能通过派生类对象在外部直接访问。-在protected继承中,基类的publicprotected成员在派生类中都变成了protected,因此只能在派生类内部访问,外部无法访问。-在private继承中,基类的publicprotected成员在派生类中都变成了private,同样只能在派生类内部访问。使用建议:-尽量使用public继承,因为这样符合“is-a”关系,并且基类的接口在派生类中仍然可用。-protected继承private继承破坏了基类的接口,使得基类的公有成员在派生类外部不可用,这通常表示“is-implemented-in-terms-of”关系,但使用组合(composition)可能比私有继承更好(引用3)。综上所述,protected成员在继承体系中的作用是为派生类提供访问基类实现的途径,同时对外部隐藏细节。合理使用protected可以提高代码的封装性和可维护性(引用1、5)。</think>### C++中的protected继承:使用场景与规则详解 在C++面向对象编程中,`protected`访问权限在继承体系中扮演着关键角色。以下是其核心规则和使用场景: #### 一、protected成员的基本特性 1. **访问权限规则**: - 类内部:可访问(同`private`) - 派生类内部:可访问(区别于`private`) - 类外部:不可直接访问(同`private`) ```cpp class Base { protected: int protVar; // protected成员 }; class Derived : public Base { public: void accessBase() { protVar = 42; // ✅ 派生类可访问基类protected成员 } }; int main() { Derived d; // d.protVar = 10; // ❌ 错误:外部不可访问 } ``` #### 二、protected继承的规则 当使用`protected`继承时(`class Derived : protected Base`): 1. **访问权限转换**: - 基类`public`成员 → 在派生类中变为`protected` - 基类`protected`成员 → 在派生类中保持`protected` - 基类`private`成员 → 在派生类中**不可访问** ```cpp class Base { public: void pubFunc() {} protected: void protFunc() {} private: void privFunc() {} }; class Derived : protected Base { public: void test() { pubFunc(); // ✅ 原public成员变为protected protFunc(); // ✅ 保持protected // privFunc(); // ❌ 不可访问 } }; int main() { Derived d; // d.pubFunc(); // ❌ 错误:外部无法访问(已降级为protected) } ``` #### 三、核心使用场景 1. **实现继承而非接口继承**: - 当需要复用基类实现,但**不暴露其公共接口**给派生类的外部使用者时 - 例:工具类继承,基类方法仅用于派生类内部实现 2. **构建中间抽象层**: ```cpp class AbstractDevice { protected: virtual void lowLevelInit() = 0; // 仅允许派生类实现 public: void startup() { lowLevelInit(); // 模板方法模式 // ...公共启动流程 } }; class Camera : protected AbstractDevice { protected: void lowLevelInit() override { /* 相机专用初始化 */ } }; ``` 3. **限制基类接口传播**: - 防止派生类对象被误用为基类类型 - 例:私有功能模块继承,禁止向上转型 #### 四、重要注意事项 1. **实际开发建议**: - 优先使用`public`继承(占实际使用的90%以上)[^3] - `protected/private`继承会显著降低代码可维护性[^3] - 多数情况下,**组合(composition)优于`protected/private`继承**[^5] 2. **与访问修饰符的交互**: | 继承方式 | 基类public成员 | 基类protected成员 | 基类private成员 | |---------------|----------------|-------------------|----------------| | public继承 | public | protected | 不可访问 | | protected继承 | **protected** | protected | 不可访问 | | private继承 | private | private | 不可访问 | #### 五、典型问题解决方案 **场景**:需要为派生类提供工具方法,但避免污染公共接口 ```cpp class MatrixUtils { protected: // 关键点:protected工具方法 void normalizeData(double* data, int size) { // 内部实现细节... } }; class ImageProcessor : protected MatrixUtils { public: void processImage() { double pixelData[100]; normalizeData(pixelData, 100); // ✅ 复用工具方法 // ...其他处理 } }; ``` > 此设计确保`normalizeData()`仅对派生类可见,避免外部误用[^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值