令我惊讶的是,在以下示例中,将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) {} //<<<<<<<<<<<
};
使用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的基类的时候,其名称可以用作类型。我可以理解,当使用Base表示应为私有的基类存储时。但是,至少有一个私有基类的声明会导致类型名称无法访问,这至少是意外的。
答案 0 :(得分:12)
这是有意的;参见core issue 175,甚至在[class.access.spec] p5中添加了一个示例来说明这一点:
[注意:”在派生类中,将查找基类名称 注入的类名,而不是基类的名称 声明的范围。注入的类名可能更少 可以访问的范围比基类在其作用域中的名称 被宣布。 — 尾注] [示例:
class A { }; class B : private A { }; class C : public B { A* p; // error: injected-class-name A is inaccessible ::A* q; // OK };
— 最终示例]
这不属于类名注入(有关原理,请参见Why is there an injected class name?)与C ++访问控制在名称查找之后而不是之前应用的事实之间的相互作用。