假设我有一个愚蠢的类层次结构。
class Base {
public:
Base() = default;
virtual ~Base() = default;
virtual void print() = 0;
};
class Derived : public Base {
public:
Derived() {
stuff.resize(1000);
}
void print() override {
cout << "Whatever\n";
}
private:
std::vector<int> stuff;
};
我想这样使用它:
void printIt(Base* b) {
b->print();
}
int main() {
Derived d1;
Derived d2 = d1;
printIt(&d1);
printIt(&d2);
}
这编译并且工作正常,但Clang警告我:
警告:不推荐使用'Base'的隐式复制构造函数的定义,因为它具有用户声明的析构函数
这似乎很正确 - 如果人们复制Base
会发生不好的事情,所以我会删除复制构造函数。
class Base {
public:
Base() = default;
virtual ~Base() = default;
virtual void print() = 0;
Base(const Base&) = delete;
Base& operator=(const Base&) = delete;
};
但是我得到了这个错误:
main.cpp:38:17: error: call to implicitly-deleted copy constructor of 'Derived'
Derived d2 = d1;
^ ~~
main.cpp:18:21: note: copy constructor of 'Derived' is implicitly deleted because base class 'Base' has a deleted copy
constructor
class Derived : public Base {
^
main.cpp:14:9: note: 'Base' has been explicitly marked deleted here
Base(const Base&) = delete;
^
好的......够公平的。如果我尝试明确地添加它会怎么样?
class Derived : public Base {
public:
Derived() {
stuff.resize(1000);
}
void print() override {
cout << "Whatever\n";
}
Derived(const Derived&) = default;
private:
std::vector<int> stuff;
};
然后:
main.cpp:40:17: error: call to implicitly-deleted copy constructor of 'Derived'
Derived d2 = d1;
^ ~~
main.cpp:27:9: note: explicitly defaulted function was implicitly deleted here
Derived(const Derived&) = default;
^
main.cpp:18:21: note: copy constructor of 'Derived' is implicitly deleted because base class 'Base' has a deleted copy
constructor
class Derived : public Base {
^
main.cpp:14:9: note: 'Base' has been explicitly marked deleted here
Base(const Base&) = delete;
^
没有快乐,这也是有道理的。这里有什么解决方案?我应该忽略原来的警告吗?也许我应该将Base(Base&)
等添加为protected
?
答案 0 :(得分:1)
因此,如果我复制/分配protected
,它会在没有警告的情况下编译。这似乎是一个合理的解决方案:
class Base {
public:
Base() = default;
virtual ~Base() = default;
virtual void print() = 0;
protected:
Base(const Base&) = default;
Base& operator=(const Base&) = default;
};
class Derived : public Base {
public:
Derived() {
stuff.resize(1000);
}
void print() override {
cout << "Whatever\n";
}
private:
std::vector<int> stuff;
};
void printIt(Base* b) {
b->print();
}
int main() {
Derived d1;
Derived d2 = d1;
printIt(&d1);
printIt(&d2);
}
答案 1 :(得分:0)
如果你想像Derived d2 = d1;
那样使用它,你需要做三件事:
1)使Base
复制(和移动)构造函数和赋值运算符protected
而不是deleted
委托允许/禁止复制/移动到派生类的功能
protected: Base(const Base&) = default;
protected: Base& operator=(const Base&) = default;
2)使Derived
复制(和移动)构造函数和赋值运算符public
以指示允许复制/移动
public: Derived(const Derived&) = default;
public: Derived& operator=(Derived&) = default;
3)将Derived
标记为final
,以防止有人决定再次从中获取意外切片
class Derived final: public Base