从C++中的私有模板类继承构造函数

Bar*_*ett 46 c++ templates language-lawyer

为什么类D编译,但类C没有?

class A
{
    public:
        A(int) {}
};

template <class T>
class B : private T // Note: private base class
{
    public:
       using T::T;
};

class C : public B<A>
{
    public:
        C() : B<A>(123) {}  // Error: 'class A A::A' is inaccessible
};                          //         within this context

using BA = B<A>;

class D : public BA
{
    public:
        D() : BA(123) {}  // OK
};
Run Code Online (Sandbox Code Playgroud)

我用GCC,Clang和Visual C++ 进行了测试,它们都是一样的.改变class B : private Tpublic T解决问题.但为什么?(注意using T::Tpublic.)

Rei*_*ica 42

类在其范围内A包含inject-class-name A(即,除非碰巧引用构造函数,否则A::A引用类A).

B继承这一点,所以名称A的范围内B是指在注射类名A中的范围A.但是,由于A是私有基类B,因此范围内的所有名称A都是私有的B.

C再次继承了这个,但它无法访问它A,因为它是私有的B.因此错误.请注意,错误实际上是使用A构造中的名称B<A>.

BA没有这个问题,因为定义B<A>不在任何类的范围内,所以名称A是指全局名称A而不是任何注入类名.当然,这个名字BA是公开的.

您可以通过AC以下位置限定名称来轻松解决此问题:

class C : public B<A>
{
public:
  C() : B<::A>( 123 ) {}
};
Run Code Online (Sandbox Code Playgroud)

请注意,构造函数继承在那里没有效果.问题是与访问A(注入A和继承中BC),不进入的构造.

  • 所以这是问题的简短版本:`class A {}; B级:A {}; C类:B {A a1; :: A a2; ``所以`a2`是好的,但是'a1`没有.我不敢相信我以前从未遇到过这个...... (6认同)