使用朋友声明

时间:2018-11-23 00:27:26

标签: c++ using friend crtp

我很难理解从基类继承构造函数的正确行为。 在我的特殊情况下,我有一个带有私有构造函数的crtp基类,以防止基类的实例化(作为抽象类)。 现在,crtp-base与派生类建立了友谊,派生类通过using语句继承了基类构造函数。这对于默认,复制和移动构造函数非常有效,但对自定义构造函数无效。有没有一种方法可以在不重新实现派生类中的所有构造函数的情况下实现?

#include <iostream>

template <typename d_t>
class base
{
    friend d_t;

    base()
    {
        std::cout << "base: ctor()\n";
    }
    base(base const & other) = default;
    base(base && other) = default;

    base(int)
    {
        std::cout << "base: ctor()\n";
    }
};

class derived: public base<derived>
{
public:

   using base<derived>::base;
};

int main()
{
   derived d{};
   derived d1{d};
   derived d2{std::move(d1)};
   // derived d3{1};  //does not compile!
}

编辑

AFAIK cppreference说,派生类中using声明的访问说明符不更改构造函数的可访问性,这与其他成员函数不同。但是我已经看到了这种代码的编译和运行,并且不确定我是否正确理解了使用声明。 当然,我将进一步研究其他代码,以查看发生了什么,但我想知道是否有隐藏的东西可能会错过。

1 个答案:

答案 0 :(得分:0)

简短的答案是肯定的,只要在基类中将它们公开即可。继承的构造函数在派生类中具有与在基类中相同的可访问性。无法在派生类中公开私有基类构造函数。

但是无论如何,抽象基类不能单独实例化。无需将其构造函数设为私有。

CRTP与上述任何内容无关。如果只需要friend声明使用它,则可以不使用该模式。

class base
{
public:
  base()
  {    
  }

  base(int)
  {
    std::cout << "base: ctor()\n";
  }

  virtual void foo() = 0;
};

class derived: public base
{
public:
  using base::base;

  void foo() override
  {
    // details...
  }
};

int main()
{
  derived d{};
  derived d1{d};
  derived d2{std::move(d1)};
  derived d3{1};  //Works!!
}

有关cppreference的更多信息:Using-declaration