[英]Default move constructor/assignment and deleted copy constructor/assignment
[英]How to use move constructor with deleted default consturctor
我有一段像這樣的現有代碼:
struct Base {
Base() = default;
};
struct Derive: public Base
{
Derive() = default;
Derive(const Derive&) = delete;
Derive(Derive&& p) { *this = std::move(p); }
Derive& operator = (const Derive& p) = delete;
Derive& operator = (Derive&& p) {
return *this;
}
};
int main() {
Derive p;
}
它編譯並工作。 現在我想稍微更改 class 的定義,以便 Base 或 Derived class 始終使用某些 integer 參數構造,並且永遠不會在沒有此類參數的情況下構造。
因此,如果我嘗試以下更改:
struct Base {
Base() = delete;
Base(int a_) : a{a_} {};
private:
int a; //new mandatory param;
};
struct Derive: public Base
{
Derive() = delete;
Derive(int a_) : Base(a_) {};
Derive(const Derive&) = delete;
Derive(Derive&& p) { *this = std::move(p); }
Derive& operator = (const Derive& p) = delete;
Derive& operator = (Derive&& p) {
return *this;
}
};
int main() {
Derive p{1};
}
我得到編譯錯誤
main.cpp:15:2: error: call to deleted constructor of 'Base'
Derive(Derive&& p) { *this = std::move(p); }
^
main.cpp:4:2: note: 'Base' has been explicitly marked deleted here
Base() = delete;
^
1 error generated.
顯然這種方式行不通。 那么如何修改代碼以使其編譯並且永遠不會調用任何參數構造函數而不會出錯?
問題與
Derive(Derive&& p) xxx { *this = std::move(p); }
是在xxx
部分你有一個空的成員初始化列表。 這意味着編譯器將為基礎 class 插入一個,因為在執行構造函數主體之前,所有成員都在成員初始化列表中進行了初始化。 該編譯器生成的版本看起來像
Derive(Derive&& p) : Base() { *this = std::move(p); }
而且你不能做Base()
因為它被刪除了。 你想要的是
Derive(Derive&& p) : Base(std::move(p)) {}
甚至更短
Derive(Derive&& p) = default;
您無需顯式刪除基礎 class 中的默認 ctor。 簡單地定義一個需要參數的 ctor 會阻止編譯器生成默認 ctor,因此您的基本 class 可以是:
struct Base {
Base(int a_) : a{a_} {};
private:
int a; //new mandatory param;
};
同樣,在您的派生 class 中,定義一個接受參數的 ctor 會阻止編譯器為其生成默認 ctor。 至少到目前為止,您提到的任何內容似乎都表明您需要為派生的 class 顯式定義任何特殊成員函數,因此它可以變得簡單:
struct Derive: public Base
{
Derive(int a_) : Base(a_) {};
};
...現在代碼編譯得很好,任何嘗試創建Base
或Derive
的實例而不為 ctor 指定參數的嘗試都將失敗(不會編譯)。
順便說一句,由於您將其用作基礎 class,因此您可能希望Base
將其 dtor 虛擬化。 在這里將其定義為默認值可能是合適的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.