【发布时间】:2017-09-01 18:49:49
【问题描述】:
在探索 C++ 中基于策略的设计模式时,我偶然发现了一个我找不到解决方案的问题:如何在不引用策略中的成员变量的情况下以通用方式为基于策略的类编写复制和移动构造函数上课?
这是一个例子:
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的复制构造函数使用受保护的成员变量来初始化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();
}
【问题讨论】:
-
你为什么要首先定义复制构造函数?使用零规则。
-
复制构造函数这里是一个例子,我将在实际用例场景中遵循5规则!
-
不是五法则。 零规则。在您的情况下,
Foobase遵循零规则,Foo中的所有成员都不需要特殊处理,因此您不要为Foo类编写任何特殊成员因为默认的会做所有需要的。 -
对不起,我没有定义所有的构造函数来拥有更小的示例代码
标签: c++ templates copy-constructor move-constructor policy-based-design