是否可以在运行时切换到不同的基类构造函数?

Mat*_*lia 9 c++ inheritance constructor c++11

假设我正在编写Derived并且必须继承Base,我无法控制并且有两个单独的构造函数和一个已删除的副本和移动构造函数:

struct Base {
    Base(int i);
    Base(const char *sz);
    Base(const Base&) = delete;
    Base(const Base&&) = delete;
};

struct Derived {
    Derived(bool init_with_string);
};
Run Code Online (Sandbox Code Playgroud)

现在,根据another_param我必须使用构造函数或其他函数初始化我的基类的值; 如果C++不那么严格,那就像是:

Derived::Derived(bool init_with_string) {
    if(init_with_string) {
        Base::Base("forty-two");
    } else {
        Base::Base(42);
    }
}
Run Code Online (Sandbox Code Playgroud)

(这对于计算值以直接表达式传递给基类构造函数/字段初始化器很麻烦的所有情况也很有用,但我很讨厌)

不幸的是,即使我没有看到特定的codegen或对象模型障碍这种事情,这不是有效的C++,我想不出简单的解决方法.

有什么方法我不知道吗?

Joh*_*itb 12

静态函数在这里可以正常工作

struct Base {
    Base(int i);
    Base(const char *sz);
    Base(const Base&) = delete;
    Base(const Base&&) = delete;
};

struct Derived : Base {
   using Base::Base;

   static Derived construct(bool with_string) {
      if(with_string) return { "forty-two" };
      return { 42 };
   }
};
Run Code Online (Sandbox Code Playgroud)

请注意,这不需要移动,也不需要复制构造函数.如果您希望将其作为本地,则需要将其绑定到引用以避免移动它

auto &&w = Derived::construct(true);
auto &&wo = Derived::construct(false);
Run Code Online (Sandbox Code Playgroud)

  • @RustyX返回操作数不是表达式,而是初始化列表.它始终直接指定返回值的初始化,无需复制或移动,C++ 11以上. (2认同)

M.M*_*M.M 5

当一个对象的初始化必须在代码块内发生时,当没有更好的建议时,我已经使用了这种技术:

// (Same base as your code)
#include <memory>

struct Derived : public Base {
    using Base::Base;
};

int main(int argc, char **argv)
{
    std::unique_ptr<Derived> pd;

    if ( argc == 2 )
    {
        pd = std::make_unique<Derived>(42);
    }
    else
    {
        pd = std::make_unique<Derived>("forty-two");
    }

    Derived &d = *pd;

   // use d, don't manually reset pd
}
Run Code Online (Sandbox Code Playgroud)

  • 我不认为工厂方法是"承认失败" - 它是一种既定的,易于理解的模式,如果做得对,则将逻辑与它所创造的类保持一致. (8认同)