为什么声明私有基 class 会导致无法访问类型名称?
Why does having a declaration of a private base class render a type name inaccessible?
令我惊讶的是,在以下示例中,声明 Middle 的基 class private 使得该名称在后续派生中无法作为类型使用。
class Base {
public:
Base(Base const& b) : i(b.i) {}
int i;
};
class Middle : private Base { //<<<<<<<<<<<
public:
Middle(Base const* p) : Base(*p) {}
};
class Upper : public Middle {
public:
Upper(Base const* p) : Middle(p) {} //<<<<<<<<<<<
};
因此使用 g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 编译...
g++ -std=c++11 privateBase.cpp
我得到以下诊断:
privateBase.cpp:15:9: error: ‘class Base Base::Base’ is inaccessible within this context
Upper(Base const* p) : Middle(p) {}
^~~~
privateBase.cpp:1:12: note: declared here
class Base {
^
很明显,当 Base 被用作 Middle 的基础时 class 它的名称可以作为一种类型使用。我可以理解,当 Base 用于表示应该是私有的 base class 存储时。但是,声明私有基 class 会导致无法访问类型名称,这至少是出乎意料的。
这是有意的;请参阅 core issue 175,它甚至在 [class.access.spec]p5:
中添加了一个示例来说明这一点
[ Note: In a derived class, the lookup of a base class name will find
the injected-class-name instead of the name of the base class in the
scope in which it was declared. The injected-class-name might be less
accessible than the name of the base class in the scope in which it
was declared. — end note ] [ Example:
class A { };
class B : private A { };
class C : public B {
A* p; // error: injected-class-name A is inaccessible
::A* q; // OK
};
— end example ]
这不属于 class 名称注入(基本原理,请参阅 Why is there an injected class name?)与 C++ 中访问控制在名称查找之后而不是之前应用的事实之间的相互作用。
令我惊讶的是,在以下示例中,声明 Middle 的基 class private 使得该名称在后续派生中无法作为类型使用。
class Base {
public:
Base(Base const& b) : i(b.i) {}
int i;
};
class Middle : private Base { //<<<<<<<<<<<
public:
Middle(Base const* p) : Base(*p) {}
};
class Upper : public Middle {
public:
Upper(Base const* p) : Middle(p) {} //<<<<<<<<<<<
};
因此使用 g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 编译...
g++ -std=c++11 privateBase.cpp
我得到以下诊断:
privateBase.cpp:15:9: error: ‘class Base Base::Base’ is inaccessible within this context
Upper(Base const* p) : Middle(p) {}
^~~~
privateBase.cpp:1:12: note: declared here
class Base {
^
很明显,当 Base 被用作 Middle 的基础时 class 它的名称可以作为一种类型使用。我可以理解,当 Base 用于表示应该是私有的 base class 存储时。但是,声明私有基 class 会导致无法访问类型名称,这至少是出乎意料的。
这是有意的;请参阅 core issue 175,它甚至在 [class.access.spec]p5:
中添加了一个示例来说明这一点[ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. — end note ] [ Example:
class A { }; class B : private A { }; class C : public B { A* p; // error: injected-class-name A is inaccessible ::A* q; // OK };
— end example ]
这不属于 class 名称注入(基本原理,请参阅 Why is there an injected class name?)与 C++ 中访问控制在名称查找之后而不是之前应用的事实之间的相互作用。