C++之 private public protect访问控制以及继承关系

本文详细介绍了C++中访问控制符private、protected和public的区别,并解释了在公有、受保护和私有继承下,派生类如何访问基类成员的具体规则。

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

 

访问控制

private :私有控制符。这类成员只能被本类中的成员函数类的友元函数访问。不能通过对象、指针进行访问。private成员是不能被继承到,也就是说子类是无法使用父类的private成员的,和继承类型无关。

protect:受保护控制符。这类成员可以被本类中的成员函数和类的友元函数访问,也可以被派生类的成员函数和类的友元函数访问。

不能通过对象、指针进行访问

public:共有控制符。这类成员可以被本类中的成员函数和类的友元函数访问,也可以被类作用域内的其他函数引用


继承关系

在三种不同方式的继承下,派生类对原来基类中的成员访问的方式也不一样,具体如下:
1>公有继承中:
  (1)基类的共有成员就相当于是派生类的公有成员,也就是说派生类可以像访问自身公有成员一样访问从基类继承的公有成员。
  (2)基类的保护成员就相当于是派生类的保护成员,即,派生类可以像访问自身的保护成员一样,访问基类的保护成员。
  (3)对于基类的私有成员,派生类内部成员是无法直接访问的,派生类使用者也无法通过派生类对象直接访问。
2>受保护继承中:
  (1)基类的公有成员和保护成员都相当于派生类的保护成员,派生类可以通过自身的成员函数或其子类的成员函数访问它们。
  (2)对于基类的私有成员,无论派生类内部成员或派生类的对象都无法直接访问。
3>私有继承中:
  (1)基类公有成员和受保护成员都相当于派生类的私有成员,派生类只能通过自身的成员函数访问他们。
  (2)对于基类的私有成员,无论派生类内部成员或派生类的对象都无法直接访问

<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、付费专栏及课程。

余额充值