基于策略的设计中的 C++ 复制/移动构造函数

标签 c++ templates copy-constructor move-constructor policy-based-design

<分区>

在 C++ 中探索基于策略的设计模式时,我偶然发现了一个我找不到解决方案的问题:如何以通用方式为基于策略的类编写复制和移动构造函数而不引用策略中的成员变量类(class)?

这是一个例子:

class Foobase {
public:
  Foobase(int v) :val(v) { }
protected:
  int val;
};

template <typename Base>
class Foo : public Base {
public:
  Foo(int v):Base(v) { }
  // how can I initialize Base() class without referring to it's protected members?
  Foo(const Foo<Base>& other) :Base(other.val) { }
};

int main() {
  Foo<Foobase> foo(5);
  auto foo2 = foo;
}

在上面的代码中,class Foo 的复制构造函数使用 protected 成员变量来初始化Base 类。除了上述之外,还有其他方法可以初始化 Base 吗?在这种情况下,最佳做法是什么?

更新的问题:

@LogicStuff 的回答澄清了问题的复制构造函数部分,但没有回答移动构造函数问题。请参阅更新的示例代码,其中 class Foo 也可以有成员变量。

class Foobase {
public:
  Foobase(int v) :val(v) { }
  Foobase(const Foobase&) = default;
  Foobase(Foobase&&) noexcept = default;
  Foobase& operator= (const Foobase&) = default;
  Foobase& operator= (Foobase&&) noexcept = default;
  void Print() const {
    std::cout << val << std::endl;
  }
protected:
  int val;
};

template <typename Base>
class Foo : public Base {
public:
  // works fine
  Foo(std::string str, int v):Base(v), name(str) { }

  // works fine
  Foo(const Foo<Base>& other) :Base(other), name(other.name) { }

  // I'm doubtful about this c'tor, if I move `other` for initializing Base,
  // how can I initialize `name` variable?
  Foo(Foo<Base>&& other)
    :Base(std::move(other)), name(std::move(other.name) /* will this be valid?? */) { }

  // can we have copy and assignment operator for this class?

  void Print() {
    std::cout << "name = " << name << std::endl;
    Base::Print();
  }

private:
  std::string name;
};

int main() {
  Foo<Foobase> foo("foo", 5);
  auto foo2 = std::move(foo);
  foo2.Print();
}

最佳答案

您可以简单地使用Base 的复制构造函数:

Foo(const Foo<Base>& other) : Base(other) { }

或者根本不定义它并将其留给编译器,如果你不打算在那里做一些额外的事情的话。

实际上,它看起来像这样,您的示例仍然可以编译:

template <typename Base>
class Foo : public Base {
public:
  using Base::Base;
};

编辑后:

现在你必须补充一个带两个参数的构造函数(就像你所做的那样):

template <typename Base>
class Foo : public Base {
public:
  Foo(std::string str, int v) : Base(v), name(str) { }

  void Print() {
    std::cout << "name = " << name << std::endl;
    Base::Print();
  }

private:
  std::string name;
};

但您还定义了特殊成员函数,否则编译器将完全相同地生成它们(这意味着它们是正确的)。您的原始示例也是如此。 Foo 的两个版本都是可移动构造的。

关于基于策略的设计中的 C++ 复制/移动构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46006365/

相关文章:

c++ - 将为此代码运行复制构造函数吗?

c# - 写一个二进制文件到struct c#

c++ - 通过指向虚函数的成员函数指针调用基类成员函数实现

c++ - 派生类中的函数模板特化

c++ - 如何确定 C++ 中实例化容器模板的容器模板类型

c++ - 错误 : templated copy constructor calls itself

c++ - 我们如何注册具有特定文件扩展名的 Shell 扩展

c++ - IWebBrowser2::Navigate2 错误处理

python - Django 中的模板不存在

c++ - 在我使用完这个对象之前调用析构函数来销毁对象