【问题标题】:Inheriting constructors vs forwarding继承构造函数与转发
【发布时间】:2015-03-13 02:58:02
【问题描述】:

C++11 允许继承构造函数,从而可以避免大量样板文件,尤其是像包装类这样的东西。但是,您似乎已经可以仅使用可变参数模板来实现此功能。

class B
{
public:
 B(int){//do something}
 B(int, char){//do something}
};

使用继承构造函数:

class D : public B
{
public:
 using B::B; 
};

使用可变参数模板并转发:

class D : public B
{
public:
 template <typename...Args>
 D(Args&&... args) : B(std::forward<Args>(args)...)
 {
 }
};

虽然一致性(对using 以相同的方式对待构造函数和方法)和易用性是将继承的构造函数引入语言的很好理由,但还有其他原因可以说明第一种解决方案优于第二种解决方案吗?我发现讨论继承构造函数的 CWG 文档(N1890N1898)只需注意以下内容并继续:

除了历史事故之外,也不会阻止使用它来为构造函数工作 至于普通的成员函数。如果构造函数被称为“ctor”或“constructor” 而不是用他们的班级名称来引用,这会奏效。我们 建议将此作为继承构造函数的机制。

【问题讨论】:

标签: c++ c++11 inheriting-constructors


【解决方案1】:

最大的原因是完美的转发并不完美。简单案例:

struct B {
    B(int* ) { .. }
};

现在考虑:

D d{0};

如果我们继承构造函数,这可以正常工作。如果我们完美转发,我们将尝试构造B(int ),因为0 推导出为int,这是一个不存在的构造函数。失败!

其他失败案例包括大括号初始化、仅声明的静态 const 数据成员、重载函数和位域。

【讨论】:

  • 附带说明:这就是为什么人们不应再使用整数文字作为指针的初始值设定项的原因之一,而应仅使用 nullptr
【解决方案2】:

完美的转发并不完美。特别是,0 作为实际参数减少到int,而不是表示一般的空值。因此,使用带有指针参数的构造函数,0 将作为继承构造函数的实际参数,但不适用于转发。

当问题(我们真的需要继承构造函数)播出时,我想我提到的另一个原因是继承构造函数是概念上简单事物的简单符号,用于简单的上下文中班级。 C++中有足够的强制复杂度和强制样板。

【讨论】:

    【解决方案3】:

    维护问题(编译器错误)可能会导致偏好“使用”:

    struct Base
    {
        Base(int) {}
    };
    
    struct Derived : public Base
    {
        using Base::Base;
    };
    
    struct DerivedTemplate : Base
    {
        template <typename...Args>
        DerivedTemplate(Args&&... args)
        : Base(std::forward<Args>(args)...)
        {}
    };
    
    int main()
    {
        // error: no matching function for call to ‘Derived::Derived(int, int)’
        Derived d(1, 2);
    
        // In instantiation of ‘DerivedTemplate::DerivedTemplate(Args&& ...) [with Args = {int, int}]’:
        // required from here
        // error: no matching function for call to ‘Base::Base(int, int)’
        DerivedTemplate dt(1, 2);
    }
    

    另外,每个模板实例化都是不同的构造函数(虽然使用不乘)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-01
      • 2023-04-03
      • 2013-03-21
      • 2011-09-09
      • 2014-11-22
      相关资源
      最近更新 更多