C++ 为什么派生类的这个定义是非法的?

C++ 为什么派生类的这个定义是非法的?,c++,class,c++11,inheritance,C++,Class,C++11,Inheritance,为什么从_Private派生的派生类_是非法的? 我注意到成员函数有一个对基类的引用,但是为什么它不能有一个对基类的引用呢 class Base { public: void pub_mem(); // public member protected: int prot_mem; // protected member private: char priv_mem; // private member }; struct Pub_Derv : public Base { //

为什么从_Private派生的派生类_是非法的? 我注意到成员函数有一个对基类的引用,但是为什么它不能有一个对基类的引用呢

class Base {
public:
  void pub_mem(); // public member
protected:
  int prot_mem; // protected member
private:
  char priv_mem; // private member
};

struct Pub_Derv : public Base {
  // legal
  void memfcn(Base &b) { b = *this; }
};

struct Priv_Derv : private Base {
  // legal
  void memfcn(Base &b) { b = *this; }
};

struct Prot_Derv : protected Base {
  // legal
  void memfcn(Base &b) { b = *this; }
};

struct Derived_from_Public : public Pub_Derv {
  // legal
  void memfcn(Base &b) { b = *this; }
};

struct Derived_from_Private : public Priv_Derv {
  // illegal
  void memfcn(Base &b) { b = *this; }
};

struct Derived_from_Protected : public Prot_Derv {
  // legal
  void memfcn(Base &b) { b = *this; }
};
表情

b = *this;

需要调用从
*this
Base
类型的左值的隐式转换,以便调用隐式声明的
Base::operator=(const Base&)
。此转换通过路径
派生自\u Private->Priv\u Derv->Base
。由于
Priv\u Derv
Base
作为私有基,因此从
private
派生的
无法访问第二个链接。

Priv\u Derv
私有继承
Base
。这意味着只有类本身知道它也是
Base
,并且只有
Priv\u Derv
的成员函数才能使用
Base
的成员

您可以稍后让
派生自\u Private
Priv\u Derv
公开继承。这是合法的。但不幸的是,由于以前的私有继承,似乎
派生自\u private
没有
Base
作为基类

因此,您的成员函数将无法编译:

    void memfcn(Base &b) { b = *this; }

*此
是从\u Private
派生的
,但将其转换为
类是非法的,因为由于私有继承,与该类没有已知关系

遗传既能提供亚型又能提供结构扩展

当您从基类私下继承时,您没有子类型,只有结构扩展。然后(在您有问题的情况下)当您编写
b=*this
*this
不是类型的
Base
,因为您使用了它的私有继承


私有继承通常用于(这并不意味着它是一种好的实践)轻松构造非常简单的组合(有一个基,但不是是一个基)。

类的名称作为公共成员插入到其自身的范围中。这就是所谓的。派生类
derived\u from\u Private
中的
Base
的名称查找将找到其注入的类名,而不是正常的类名。由于
Base
的注入类名被视为
Base
的公共成员,因此被视为
Priv\u Derv
的私有编号,因此在
派生自\u private
中无法访问

引自:

[ 注意:在派生类中,基类名称的查找将在声明基类的作用域中找到注入的类名,而不是基类的名称。注入的类名可能比声明基类的作用域中的基类名称更难访问- 尾注 ] [ 例如:

- 结束示例 ]


你对关键字protected和private的理解是什么?在哪个上下文中?对于private继承,实际上没有到基类的隐式转换(你必须使用cast),只要我使用基类作为参数。编译器给出了一个错误。你是什么意思?struct派生自private:public Priv{//非法无效memfcn(Base&b){};这也是非法的!!!!为什么???在这种情况下,编译器认为您正在谈论的是私有基类
base
,然后抱怨,如果您想谈论在全局范围内定义的类型,请写入
::base
。但我没有使用base的成员。即使我没有将*分配给base,只要我有一个base参数(引用或副本)编译器给了我一个错误。@JingleiRuan有趣!似乎私有继承会影响非限定名称查找。请使用::Base而不是Base显式引用右侧(此处为全局)命名空间,它将被编译。@JingleiRuan是的,就是这样!根据,它似乎是一个编译器错误,但这个编译器问题并不影响我初始答案的有效性。您将看到::变通方法将以空体编译,但在您尝试赋值时失败。它与赋值无关。编译器只要我把Base作为参数传递,就会给我一个错误。@JingleiRuan啊,这是真的。xskxzr提供的答案是正确的。但是你可以使用
::Base
来解决这个问题。
class A { };
class B : private A { };
class C : public B {
  A* p;             // error: injected-class-name A is inaccessible
  ::A* q;           // OK
};