4

我有一个关于从私有继承基类的类继承的简单问题,即我们有

class Base {};
class Heir: private Base {};
class HeirsHeir : public Heir {};

了解HeirsHeir无法访问 '其' 的任何内容Base。特别是,它不能有一个方法返回Base &对自身的引用。但是为什么它不能返回对另一个Base 对象的引用呢?那么为什么以下代码无法编译:

class Base {};
class Kid : private Base {};
Base instance;
class Grandkid : public Kid
{
    const Base &GetInstance  () const
    { return instance; }
};

至少我的编译器(MinGW 5.3,即 Windows 的 gcc)给出了

error 'class Base Base::Base' is inaccessible at {}; 
error: within this context const Base &getInstance () const

据我了解,这没有意义,因为此时我没有调用 Base 的构造函数,而是返回一个引用(对 Base 实例)。

请注意,可以通过使用来修复错误

const ::Base &GetInstance  () const
{ return instance; }

这肯定与 C++03 §11.2/3 相关联(参见 [ C++ 私有继承和静态成员/类型

注意:私有基类的成员可能无法作为继承的成员名称访问,但可以直接访问。

但我不明白为什么这是必要的。有人可以解释一下吗?

4

2 回答 2

2

Base名称查找找到注入的类名Base(并因此被 继承GrandKid)。这是正确的,因为注入的类名的范围比类的命名空间范围名更近。但是,这个注入的类名是不可访问的,GrandKid因为它是私有的Kid

在编译器的错误消息中,Base::Base不是指构造函数,而是指Base注入到Base. 请注意,当使用它的上下文强制将名称解释为类型时,您实际上可以Base::Base合法地使用,就像在这个有效但卑鄙的代码中一样:

class Foo {};

std::vector<Foo::Foo::Foo::Foo> v;

[现场示例]

但是,当使用的上下文Base::Base允许引用函数时,它会解析为构造函数而不是类名(C++11 [class.qual] 3.4.3.1/2)

于 2017-09-29T10:38:53.713 回答
0

我认为编译器无法识别 Base 是一个类名,并在您想要访问 Base 成员时识别它。

这也编译:

class Base {};
class Kid : private Base {};
Base instance;
class Grandkid : public Kid
{
    const class Base &GetInstance  () const
    { return instance; }
};

错误的使用是这样的:

class Base {
public:
    struct BaseStruct { int a; };
};
class Kid : private Base {
public:
    struct KidStruct { int a; };
};
Base instance;
class Grandkid : public Kid
{
    const class Base &GetInstance  () const
    { return instance; }

    const Kid::KidStruct kidStruct;
    const Base::BaseStruct baseStruct;
};

kidStruct没有错误,因为继承是公共的,但baseStruct不可访问。

于 2017-09-29T10:30:47.920 回答