尝试使用复制/移动 ctors/赋值运算符和 dtor(五规则)的实现来解决与抽象基类相关的错误C2248 ,并且出现了一些问题:
1) 为什么在自动处理 unique_ptr 数据成员时适用主要与 dtor 相关的 5 规则?dtor 实现应该留空正确,因为一旦它们的所有者超出范围,unique_ptrs 就会自动销毁?
2) 假设另一个类具有相同类型向量的 std::unique_ptr 类型成员。为了让这个类是可复制的,它必须有一个复制 ctor 和复制赋值运算符来克隆 unique_ptr 数据成员?我已经看到了这个解决方案,但似乎原始发帖人只是切换到 shared_ptr 只是为了消除错误而很少考虑所有权管理。这是正确的策略吗?
3) 考虑与上述问题 2 有关 unique_ptr 向量的相同情况。dtor 是否应该包括对 clear() 向量的调用?
4) Derived1 的赋值运算符不正确。但是基类应该具有复制和移动赋值运算符,因为它具有复制/移动 ctor(4/5 规则)。这些实际上不能在类之外使用,因为它是抽象的,因此不会分配实例。但是我如何利用派生类中的这段代码呢?每个派生类都需要能够移动/复制基本数据成员及其自己的数据成员。我不知道该怎么办。
#include <algorithm>
#include <memory>
#include <vector>
#include <iostream>
class Base{
public:
Base() : m_subBases(){};
/* copy ctor */
Base(const Base& other) : m_subBases(){
*this = other;
};
/* move ctor */
Base(Base&& other) : m_subBases(){
*this =std::move( other);
};
/* Move assignment operator*/
Base& operator=(Base&& other){
m_subBases = std::move(other.m_subBases);
return *this;
};
/* Copy assignment operator */
Base& operator=(const Base& other){
for(int i = 0; i < other.m_subBases.size(); i++)
m_subBases.push_back(other.m_subBases[i]->clone());
return *this;
};
/* virtual dtor */
virtual ~Base(){
m_subBases.clear();
};
/* Used for creating clones of unique_ptrs */
virtual std::unique_ptr <Base> clone() const= 0;
/* Do something */
virtual void execute(float f) = 0;
//Omitted data member access methods
protected:
std::vector < std::unique_ptr <Base> > m_subBases;
};
class Derived1 : public Base{
public:
Derived1() : Base(){};
/* copy ctor */
Derived1(const Derived1& other) : Base(other){
*this = other;
};
/* move ctor */
Derived1(Derived1&& other) : Base(std::move(other)){
*this = std::move(other);
};
/* Move assignment operator*/
Derived1& operator=(Derived1&& other){
//This is redundant when called in the move ctor because
// of the call to Base(std::move(other))
m_subBases = std::move(other.m_subBases);
m_string = other.m_string;
return *this;
};
/* Copy assignment operator */
Derived1& operator=( const Derived1& other){
//This is redundant when called in the copy ctor because
// of the call to Base(other)
for(int i = 0; i < other.m_subBases.size(); i++)
m_subBases.push_back(other.m_subBases[i]->clone());
m_string = other.m_string;
return *this;
};
/* virtual dtor */
virtual ~Derived1(){};
/* Used for creating clones of unique_ptrs */
virtual std::unique_ptr <Base> clone() const{
return std::unique_ptr <Base> (new Derived1(*this));
};
virtual void execute(float f){
std::cout << "Derived1 " << f << std::endl;
};
protected:
std::string m_string;
};