为何派生类及Derived_from_Private类定义非法?含Base引用为何不可?
最常见的原因是你在派生类里直接碰了基类的私有成员,咱们看个实打实的例子:
class Base { private: int secret_num; // 基类的私有成员,对外(包括派生类)都是藏起来的 }; // 这个派生类会报错 class Derived : public Base { public: void change_secret() { secret_num = 42; // 这里直接访问Base的私有成员,编译器会直接怼你 } };
C++的访问规则卡得很死:基类的私有成员只能自己用,或者给自己的友元用,派生类不管是public、protected还是private继承,都没资格直接碰。要是真得改这个成员,得让Base给你留个接口——比如整个set_secret(int num)的public方法,或者把成员改成protected。
当然也有其他可能的非法情况,比如基类是抽象类但你没实现纯虚函数,或者多重继承搞出了歧义,但90%的情况都是上面这种碰了私有成员的问题。
先明确,Derived_from_Private大概率是私有继承了Base的类,咱们先看两种常见的非法场景:
场景1:在派生类成员函数里,通过Base引用访问基类的protected成员
比如这段代码:
class Base { protected: void protected_method() {} // 基类的保护成员,只有自己和派生类能碰自己的这个成员 public: void public_method() {} }; class Derived_from_Private : private Base { public: void mess_with_base(Base& some_base) { some_base.protected_method(); // 这里会报错! } };
为啥不行?你得搞清楚:派生类能访问的是自己身上的那个基类子对象的protected成员,不是随便哪个Base对象的。比如你要是想调用自己的protected_method,直接写this->protected_method()就行,但拿个外部传入的Base引用去调用它的protected成员,就越界了——你又不是这个Base对象的派生类,凭啥碰人家的保护成员?
场景2:外部代码想把Derived_from_Private对象转成Base&
比如你在main里写:
Derived_from_Private d; Base& b_ref = d; // 这里直接报错!
这是私有继承的特性决定的:私有继承是“基于Base实现”,不是“是一个Base”,所以对外要隐藏继承关系。外部代码根本不知道Derived_from_Private是从Base来的,自然不能把它当成Base用。
哦对了,要是你只是单纯“持有”Base的引用——比如把它当函数参数、或者类的成员变量,这完全合法!比如:
class Derived_from_Private : private Base { private: Base& my_base; // 没问题,就是存个引用 public: Derived_from_Private(Base& b) : my_base(b) {} void call_public_stuff() { my_base.public_method(); // 合法,因为public_method是Base对外公开的 } };
所以不是不能持有引用,是你持有引用后做了越权的操作,或者外部想做非法的类型转换。
内容的提问来源于stack exchange,提问作者Jing

