C++ 为什么派生类的这个定义是非法的?
为什么从_Private派生的派生类_是非法的? 我注意到成员函数有一个对基类的引用,但是为什么它不能有一个对基类的引用呢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 { //
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
};