2013-05-27 23 views
12

Clang documentation整齊地解釋說,是否也是用戶定義的繼承的默認構造函數?

如果一個類或結構有沒有用戶定義的默認構造函數,C++ 不允許默認構造它的一個常量例如像 這個([dcl.init] ,P9)

以下代碼具有這樣爲Base用戶定義的默認的構造,但g ++以及鏘不同意爲Derived默認構造是否是用戶定義的,即使Derived不明確地繼承所有的層構造(使用new C++11 inheriting constructors feature

#include <iostream> 

class Base 
{ 
public: 
    Base(): b_(0) {} // look! user-defined default constructor 
    void print() const { std::cout << b_ << "\n"; } 
private: 
    int b_; 
}; 

class Derived 
: 
    public Base 
{ 
    using Base::Base; // does this constitute a user-defined default constructor? 
}; 

int main() 
{ 
    Base const b; 
    b.print(); // 0 for g++ & CLang 

    Derived const d; 
    d.print(); // 0 for g++, Clang: "default initialization of an object of const type 'const Derived' requires a user-provided default constructor" 
} 

克++ 4.8愉快地接受這個代碼,但鏘3.3沒有。標準說什麼?

:無爲Base用戶定義的默認的構造,既克++ 4.8也不鏘3.3接受Base const b;(而例如克++ 4.7.2先前接受的是)。鑑於g ++知道該規則,我認爲這意味着g ++將Derived的默認構造函數視爲用戶定義的。但是Clang 3.3認爲不然。

UPDATE:基於@JesseGood的回答是0/1參數構造函數永遠不會遺傳的,我試圖改變Base構造函數

Base(int b = 0, void* = nullptr): b_(b) {} 

,但它不能解決鏘錯誤。

+0

你是對的我誤解了這個問題。 –

回答

7

Clang是正確的。

約const的實例相關的通道是從8.5p7:

如果程序調用用於 常量限定類型T的對象的默認的初始化,T應爲一個類類型與用戶提供的 默認構造函數。

由於Base(): b_(0) {}是用戶提供的,Base const b;是好的。

下一個重要的部分是12.9p3:

對於在候選集合中繼承 構造比具有其他構造的每個非模板構造沒有參數或具有一個 複製/移動的構造單個參數,構造函數是 隱含聲明具有相同的構造函數特性除非 有一個用戶聲明的構造函數具有相同的簽名 類中使用聲明出現

這裏的重要部分是粗體文本。我相信這會排除你的情況,因爲Base()是一個沒有參數的構造函數。這意味着Derived沒有用戶提供的默認構造函數(儘管仍然隱式聲明)。

這也意味着,從基類的默認,複製和移動構造函數是永遠不會繼承。

+0

+1感謝您的回答。如果我將'Base'構造函數簽名更改爲'Base(int b = 0,void * = nullptr):b_(b){}',則默認構造函數被抑制。但Clang仍然給出了「Derived」(並且g ++接受它)的錯誤。具有2個默認參數的構造函數是否也算作不帶參數的非繼承構造函數? – TemplateRex

+2

@rhalbersma:是的,它仍然算作一個沒有參數的非繼承ctor。 'Base(int)'和'Base(int,void *)'雖然被繼承。 (但是,默認參數不會被繼承)。 –

+0

謝謝,我接受了你的回答。 – TemplateRex

相關問題