[英]Inheriting constructors vs forwarding
C ++ 11允許繼承構造函數,從而可以避免大量的樣板,尤其是類似於包裝類的東西。 但是,似乎您已經可以使用可變參數模板實現此功能。
class B
{
public:
B(int){//do something}
B(int, char){//do something}
};
使用繼承構造函數:
class D : public B
{
public:
using B::B;
};
使用可變參數模板並轉發:
class D : public B
{
public:
template <typename...Args>
D(Args&&... args) : B(std::forward<Args>(args)...)
{
}
};
雖然一致性(對待構造函數和方法的相同方式using
)和易用性很好的理由把繼承構造成的語言,還有沒有其他原因的第一個解決方案應首選第二? 我發現討論繼承構造函數的CWG文檔( N1890和N1898 )只是注意以下內容並繼續:
僅僅是一個歷史事故阻止使用它來為構造函數和普通成員函數工作。 如果構造函數被稱為“ctor”或“構造函數”而不是被其類的名稱引用,那么這將起作用。 我們建議將其作為繼承構造函數的機制。
最重要的原因是完美轉發並不完美。 簡單案例:
struct B {
B(int* ) { .. }
};
現在考慮:
D d{0};
如果我們繼承構造函數,這很好。 如果我們完美轉發,我們將嘗試構造B(int )
,因為0
推導為int
,這是一個不存在的構造函數。 失敗!
其他故障情況包括支撐初始化,僅聲明的靜態const數據成員,重載函數和位域。
完美轉發並不完美。 特別是,0作為實際參數減少為int
而不是表示一般的nullvalue。 因此,對於構造函數采用指針參數, 0
將作為繼承構造函數的實際參數,但不用於轉發。
我認為我曾經提到的另一個原因是,問題(我們真的需要繼承構造函數)是否被播出,繼承構造函數是一個簡單的符號,用於概念上簡單的事情,用於簡單類的上下文中。 在C ++中有足夠的強制復雜性和強制樣板。
維護問題(編譯器錯誤)可能會導致'使用'的偏好:
struct Base
{
Base(int) {}
};
struct Derived : public Base
{
using Base::Base;
};
struct DerivedTemplate : Base
{
template <typename...Args>
DerivedTemplate(Args&&... args)
: Base(std::forward<Args>(args)...)
{}
};
int main()
{
// error: no matching function for call to ‘Derived::Derived(int, int)’
Derived d(1, 2);
// In instantiation of ‘DerivedTemplate::DerivedTemplate(Args&& ...) [with Args = {int, int}]’:
// required from here
// error: no matching function for call to ‘Base::Base(int, int)’
DerivedTemplate dt(1, 2);
}
此外,每個模板實例化都是一個不同的構造函數(使用時不會相乘)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.