在 C++ 的访问控制体系中,"内部"、"外部"、"派生类"、"友元"是判断成员能否被访问的四个关键上下文。下面结合 public、private、protected 三个访问控制符,逐一解释它们的含义与交互规则。
四个访问上下文的定义
-
内部(当前类/结构体内部)
指当前类的成员函数、静态成员函数、友元函数,以及类模板的特化实现内部。
-
无论成员是 public、protected 还是 private,内部代码均可访问。
-
示例:
cppclass Base { private: int priv; protected: int prot; public: int pub; void func() { priv = 1; // ✅ 内部可访问 private prot = 2; // ✅ 内部可访问 protected pub = 3; // ✅ 内部可访问 public } };
-
-
外部(类外部的普通代码)
指不属于该类、其派生类或友元的普通函数、其他类的成员函数等。
-
仅能访问 public 成员。
-
示例:
cppvoid external() { Base obj; obj.pub = 10; // ✅ 外部可访问 public // obj.prot = 20; // ❌ 编译错误:protected 不可外部访问 // obj.priv = 30; // ❌ 编译错误:private 不可外部访问 }
-
-
派生类(继承自当前类的子类)
指通过继承关系获得的子类,其成员函数和静态成员。
-
可访问基类的 public 和 protected 成员。
-
不可访问基类的 private 成员(即使通过继承,private 成员在派生类中仍存在但不可见)。
-
注意:继承方式(public/protected/private 继承)会影响基类成员在派生类中的"可见访问级别",但不改变其原始声明的访问属性。
-
示例:
cppclass Derived : public Base { public: void accessBase() { pub = 1; // ✅ 可访问基类 public prot = 2; // ✅ 可访问基类 protected // priv = 3; // ❌ 编译错误:基类 private 不可访问 } };
-
-
友元(friend)
通过 friend 关键字显式授权的函数或类,可突破访问控制限制。
-
友元不是继承关系,也不受继承方式影响。
-
友元可访问该类的所有成员(包括 private 和 protected)。
-
友元关系不可传递、不可继承。
-
示例:
cppclass Friend; // 前向声明 class Base { private: int priv; protected: int prot; public: int pub; // 声明友元函数 friend void friendFunc(Base&); // 声明友元类 friend class Friend; }; void friendFunc(Base& obj) { obj.priv = 100; // ✅ 友元函数可访问 private obj.prot = 200; // ✅ 友元函数可访问 protected obj.pub = 300; // ✅ 友元函数可访问 public } class Friend { public: void modify(Base& obj) { obj.priv = 10; // ✅ 友元类成员可访问 Base 的 private } };
-
访问权限速查表
| 访问上下文 | public | protected | private |
|---|---|---|---|
| 内部(本类成员/静态/友元) | ✅ | ✅ | ✅ |
| 外部(普通代码) | ✅ | ❌ | ❌ |
| 派生类成员函数 | ✅ | ✅ | ❌ |
| 友元函数/类 | ✅ | ✅ | ✅ |
关键补充说明
-
protected 的"继承可见性"细节
- protected 成员在派生类中可访问,但仅限于通过派生类对象自身的 this 指针访问。
- 不能通过基类指针/引用访问其他对象的 protected 成员(即使该对象是派生类实例)。
cppclass Base { protected: int val; }; class Derived : public Base { public: void test(Derived& other, Base& baseRef) { val = 1; // ✅ 访问自己的 protected other.val = 2; // ✅ 访问同类型派生类对象的 protected // baseRef.val = 3; // ❌ 编译错误:不能通过基类引用访问其他对象的 protected } }; -
继承方式对成员"可见级别"的影响
继承方式会"降级"基类成员在派生类接口中的访问级别,但不改变其原始声明属性:
cppclass Base { public: int pub; protected: int prot; private: int priv; }; // public 继承:保持原级别 class PubDer : public Base { // pub → public, prot → protected, priv → 不可见 }; // protected 继承:public/protected 都变为 protected class ProtDer : protected Base { // pub → protected, prot → protected, priv → 不可见 }; // private 继承:public/protected 都变为 private class PrivDer : private Base { // pub → private, prot → private, priv → 不可见 }; -
友元的单向性与非传递性
- A 声明 B 为友元,不代表 B 自动将 A 视为友元。
- A 的友元不能自动访问 A 的派生类的 private 成员(除非派生类也显式声明该友元)。
理解这四个上下文与三种访问控制符的组合关系,是掌握 C++ 封装、继承与多态机制的基础。如有具体代码场景或设计困惑,可进一步提供细节进行分析。