c++ - 不能使用友好的 CRTP 类的私有(private)构造函数

标签 c++ friend crtp

我有使用此设计的代码,经过简化以获得此 MCVE - 代码和编译器错误随之而来。

基本问题是,我认为与 CRTP 类建立友好关系将允许模板化基类访问派生 CRTP 类的私有(private)成员,包括其私有(private)构造函数。

但显然不是。为什么?

this code on wandbox :

#include <iostream>
using namespace std;

template <class CRTP>
class Base
{
  friend CRTP;
public:
  static void Factory()
  {
      cout << "Base::Factory()" << endl;
      CRTP x;
      x.Hello();
  }
  virtual void Hello() { cout << "Base::Hello()" << endl; }
protected:
  Base() { cout << "Base::Base()" << endl; }
  virtual ~Base() { cout << "Base::~Base()" << endl; }
};


class Derived final : public Base<Derived>
{
public:
  void Hello() override;
private:
  Derived() { cout << "Derived::Derived()" << endl; }
  ~Derived() override { cout << "Derived::~Derived()" << endl; }
};

int main()
{
    Derived::Factory();
    // Expected output:
    //   Base::Factory()
    //   Base::Base()
    //   Derived::Derived()
    //   Derived::Hello()
    //   Derived::~Derived()
    //   Base::~Base()
}

并得到这个编译器错误(来自 clang 9.0.0,但 gcc 以同样的方式提示):

prog.cc:12:12: error: calling a private constructor of class 'Derived'
      CRTP x;
           ^
prog.cc:33:14: note: in instantiation of member function 'Base<Derived>::Factory' requested here
    Derived::Factory();
             ^
prog.cc:27:3: note: declared private here
  Derived() { cout << "Derived::Derived()" << endl; }
  ^
prog.cc:12:12: error: variable of type 'Derived' has private destructor
      CRTP x;
           ^
prog.cc:28:11: note: declared private here
  virtual ~Derived() { cout << "Derived::~Derived()" << endl; }
          ^
2 errors generated.

(仅供引用:用例是我希望模板基类通过静态工厂控制(CRTP)派生类实例的生命周期 - 包括构造。所以我希望派生类将其构造函数声明为私有(private)的,但可访问父类的静态工厂方法。此示例显示了在堆栈上创建的派生类实例,但如果它在堆中创建(并返回),则会出现相同的错误。)

最佳答案

你有 friend在错误的类中声明。 Derived需要申报Base<Derived>作为 friend ,因为 friend 可以访问私有(private)成员。 (一个类声明另一个类是 friend 。一个类不声明自己是另一个类的 friend 。)

你要添加

friend Base<Derived>;

进入Derived类声明。

关于c++ - 不能使用友好的 CRTP 类的私有(private)构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55383909/

相关文章:

c++ - 在 Qt 中将父级添加到 UI 对象

c++ - 指向模板聚合类型的指针上的reinterpret_cast 的安全性

c++ - 如何使用递归反转链表?

c++ - CRTP 复制方法警告潜在的内存泄漏

c++ - MsBuild 并行编译和构建依赖项

c++ - 关于来自 VC12 和 VC14 的 c++ 友元和继承的不同行为

类的 C++ 友元函数无法访问封装类

具有私有(private)构造函数的 C++ 静态列表

c++ - 不完整类型的无效使用

c++ - 如何将 CRTP 与可变参数模板一起使用?