【问题标题】:Workaround for inherited constructor and additional variables继承的构造函数和其他变量的解决方法
【发布时间】:2018-12-21 13:09:14
【问题描述】:

我需要一个变通方法或一个很好的解决方案来初始化基类和子类中的一堆常量类变量

问题很简单,我得到了一个有两个构造函数的基类,子类中有两个相同的构造函数

class BASE {
    int a;

    int func(float x) { // just a dummy to show that this function
        return (a = (int) x) + 2; // modifies a
    }
public:
    const int b;

    BASE(const int b) : b(b) {} // doesn't use a
    BASE(const float x) : a(0), b(func(x)) {}
};

struct SUB: public BASE {
    const int c;
    const int d;

    SUB(const int b) : BASE(b), c(b), d(c + 3) {}
    SUB(const float x) : BASE(x), c(b), d(c + 3) {}
};

子类需要从 BASE 中调用构造函数来初始化 BASE 中的类变量,然后子类初始化剩余的变量

到目前为止一切都很好,但问题是 SUB 的两个构造函数的功能完全相同,只是从 BASE 调用不同的构造函数

我想要这样的东西

    SUB() : c(b), d(c + 3) {} // BASE() needs to be defined
    SUB(const int b) : BASE(b), SUB() {}
    SUB(const float x) : BASE(x), SUB() {}

但这不起作用,因为“对委托构造函数的调用应该是唯一的成员初始化器”...

将初始化列表之外的所有内容移出不起作用,因为这些是 const 类变量

【问题讨论】:

    标签: c++ constructor initialization superclass class-variables


    【解决方案1】:

    你可以为你的派生类创建一个“转发构造函数”:

    struct SUB: public BASE {
        const int c;
        const int d;
    
        template <class... T>
        SUB(T&&... a) : BASE(std::forward<T>(a)...), c(b), d(c + 3) {}
    };
    

    这将接受任意参数并将它们转发到BASE。当然,它只会在使用对BASE 有效的参数调用时编译,但这适用于所有情况。

    如果您想要/需要超级正确,您可以使用 SFINAE 对 std::is_constructible&lt;BASE, T&amp;&amp;...&gt; 之类的东西设置构造函数,但我不会打扰。

    【讨论】:

      【解决方案2】:

      不幸的是,这是语言的规则,如果您有 delegating constructor,它必须是初始化列表的唯一部分。

      您需要解决该限制,例如通过复制默认构造函数初始值设定项列表:

      SUB(const int b) : BASE(b), c(b), d(c + 3) {}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-21
        • 2014-11-22
        • 2014-12-27
        • 2017-12-30
        相关资源
        最近更新 更多