Joh*_*tes 10 c++ injected-class-name
令我感到惊讶的是,在下面的示例中,声明Middle的基类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) {} //<<<<<<<<<<<
};
Run Code Online (Sandbox Code Playgroud)
用g ++编译(Debian 6.3.0-18 + deb9u1)6.3.0 20170516 ......
g++ -std=c++11 privateBase.cpp
Run Code Online (Sandbox Code Playgroud)
我得到以下诊断:
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 {
^
Run Code Online (Sandbox Code Playgroud)
很明显,Base被用作Middle的基类,它的名字可以作为一种类型使用.我可以理解,当Base用于表示应该是私有的基类存储时.但是,拥有私有基类的声明使得类型名称无法访问似乎至少是意外的.
T.C*_*.C. 12
这是有意的; 看看核心问题175,它甚至在[class.access.spec] p5中添加了一个说明这个的例子:
[ 注意:在派生类中,基类名称的查找将在声明它的作用域中找到inject-class-name而不是基类的名称.inject-name的名称可能比声明它的作用域中的基类名称更不易访问.- 尾注 ] [ 示例:
Run Code Online (Sandbox Code Playgroud)class A { }; class B : private A { }; class C : public B { A* p; // error: injected-class-name A is inaccessible ::A* q; // OK };- 结束例子 ]
这不属于类名注入之间的相互作用(对于基本原理,请参阅为什么有注入的类名?)以及C++访问控制在名称查找之后应用的事实,而不是之前的事实.