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

Inheriting a constructor from a private template class in C++

本文关键字:继承 构造函数 c++      更新时间:2023-10-16

为什么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
};

我测试了GCC, Clang和Visual c++,它们都是一样的。将class B : private T改为public T可以解决这个问题。但是为什么呢?(注意using T::Tpublic)

A在其作用域中包含注入的类名A(即,A::A引用类A,除非碰巧引用构造函数)。

B继承了这个,所以B作用域中的名称A指的是在A作用域中注入的类名A。但是,由于AB的私有基类,所以A作用域中的所有名称在B中都是私有的。

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

BA没有这个问题,因为定义B<A>不在任何类的作用域中,所以名称A引用全局名称A,而不是任何注入的类名。当然,BA这个名字是公开的。

您可以通过在C: 中限定名称A来轻松解决此问题。
class C : public B<A>
{
public:
  C() : B<::A>( 123 ) {}
};

注意构造函数继承在这里不起作用。问题是访问名称A(在A中注入并在BC中继承),而不是访问构造函数。