首先,对于冗长的标题感到抱歉。我遇到了一个问题,其中存在与成员相同类型的私有基础影子访问子类中的成员但不在子类定义之外。请查看以下代码:
struct PrivateBase {};
struct Base : private PrivateBase {
// Member accessors.
PrivateBase* GetPrivateBase() { return &a; }
template<typename T>
T* GetPrivateBase() { return &a; }
// Free function accessors.
friend PrivateBase* FreeGetPrivateBase(Base* b) { return &(b->a); }
template<typename T>
friend T* FreeGetPrivateBase(Base* b);
private:
// This member has nothing to do with the PrivateBase base class.
PrivateBase a;
};
template<typename T>
T* FreeGetPrivateBase(Base* b) { return &(b->a); }
struct Child : public Base {
void SomeFunc() {
// Works!1!!.
GetPrivateBase();
// Doesn't work.
//GetPrivateBase<PrivateBase>(); // (1)
// Works!1!!.
FreeGetPrivateBase(this);
// Doesn't work.
//FreeGetPrivateBase<PrivateBase>(this);
}
};
int main() {
Child c;
// Works!1!!.
c.GetPrivateBase<PrivateBase>();
// Works!1!!.
FreeGetPrivateBase<PrivateBase>(&c);
return 0;
}
我试图用g ++ - 4.8.4和clang ++ - 3.7.1编译这两者。使用clang和(1)取消注释我得到:
minimal.cc:30:20: error: 'PrivateBase' is a private member of 'PrivateBase'
GetPrivateBase<PrivateBase>();
^
minimal.cc:3:15: note: constrained by private inheritance here
struct Base : private PrivateBase {
^~~~~~~~~~~~~~~~~~~
minimal.cc:1:8: note: member is declared here
struct PrivateBase {};
^
有趣的事实是,使用非模板化访问者访问{Child}之外的a
。如果我摆脱私有基类,它也可以在带有模板化访问器的Child内部工作。
我很乐意将它归咎于编译器,但非常规的是,两个竞争者似乎都同意。有人可以解释模板化访问者,子范围和私人基类之间的相互作用吗? - 谢谢。
答案 0 :(得分:4)
在访问检查之前完成名称查找。 PrivateBase
成员函数中Child
的{{1}}的非限定名称查找PrivateBase
基类的injected class name,然后发现它是私有的,因此出错。
在GetPrivateBase<::PrivateBase>();
中使用SomeFunc()
之类的内容可以解决问题,因为限定名称查找现在会发现PrivateBase
是全局命名空间的成员,可以访问它。
这也是main
中的调用工作:main
不是成员函数的原因,因此PrivateBase
的非限定名称查找会找到命名空间成员。