protected成员仅限派生类成员函数体内直接访问,不可通过对象点号访问;继承方式不影响基类protected成员在派生类内的可访问性,只改变基类public成员的权限级别。

为什么在派生类里能用 base_protected_member,但写 d.base_protected_member 就报错
因为 protected 不是“半公开”,而是“仅限派生类成员函数体内直接访问”的硬性规则。编译器只看代码写在哪:只要在 Derived::func() 这类函数体内部,就能读写基类的 protected 成员;一旦出现在 main()、全局函数、或通过对象点号调用(哪怕对象类型是派生类),立刻拒绝。
常见错误现象:error C2248: 'Base::m_data' : cannot access private member ——注意这个提示常把 protected 误标为 private,本质是访问位置非法,不是权限不够。
- 允许:
void Derived::calc() { base_protected_member = 42; } - 禁止:
Derived d; d.base_protected_member = 42; - 禁止:
Base b; b.base_protected_member = 42;
class D : protected B 和 class D : public B 对 protected 成员的影响差异
继承方式(public/protected/private)不改变基类中已声明为 protected 的成员本身的访问性,只影响基类的 public 成员在派生类中的新权限级别。
也就是说:无论你用哪种继承方式,基类里原本 protected 的成员,在派生类中始终是 protected(可被派生类成员函数访问);但它在派生类外部永远不可见。
立即学习“C++免费学习笔记(深入)”;
-
class D : public B→B::public_func()在D中仍是public,外部可通过d.public_func()调用 -
class D : protected B→B::public_func()在D中降为protected,只能在D自己的成员函数里调,d.public_func()编译失败 - 两种方式下,
B::m_protected_data在D内部都可用,外部都不可用
什么时候该把成员设为 protected,而不是 private 或 public
选 protected 的唯一合理动机是:你明确预期子类需要复用或修改这个成员,且它不该暴露给用户——比如共享缓存、核心参数、预计算中间量。
滥用后果很直接:把本该 private 的实现细节(如 m_cached_area_valid)设成 protected,等于向所有未来子类承诺这个字段存在,后续重构会引发连锁编译错误;反过来,该 protected 的却设成 private,子类只能重复实现逻辑或加 friend,破坏继承语义。
-
public:稳定对外契约,如getArea() -
protected:留给子类定制的钩子或共享状态,如m_radius(当Circle和Sphere都需它) -
private:纯内部实现,如m_cached_area、m_dirty_flag
protected 成员在多重继承或孙子类中的行为是否可靠
可靠,但依赖继承链中每一步的权限传递。只要中间没有 private 继承截断,protected 成员就能一直向下透传。
例如:class Base { protected: int x; }; → class Derived : protected Base {} → class Grand : public Derived {}。此时 x 在 Grand 中仍是 protected,Grand::f() 可以直接访问 x。
但如果 Derived 改用 private 继承,则 x 在 Derived 中变为 private,Grand 就完全看不到它了。
真正容易被忽略的是:这种透传只发生在“派生类成员函数体内”。哪怕 Grand 能访问 x,也不能通过 Grand 对象去点号访问——那个限制从不松动。


















