2016-05-04 9 views
23

次のコードは、GCCおよび打ち鳴らすバージョンの広い範囲にコンパイル - コンパイルされ、GCC 5.3.1で実行すると、それは純粋仮想コールエラーで中止し、その後なぜgccとclangは抽象クラスを構築できますか?

A()

を印刷します。

#include <stdio.h> 

class A 
{ 
public: 
    A() { 
     printf("A()\n"); 
    } 
    virtual void b() const = 0; 
}; 

int main() 
{ 
    const A& a{}; 
    a.b(); 
    return 0; 
} 

私は(私はこの場合は、寿命延長のいくつかの並べ替えで覆われていると思いますが)一時的に参照をバインドすることは理想的ではない実現 - しかし、constのを取るメソッドを呼び出すしようとしたとき、それはまた、動作します同様の参照:便宜上

Foo({}); 

はここに打ち鳴らす3.2でコンパイルすることの例です:Compiler Explorer

+1

ポインタまたは参照によって抽象クラスを構築することはできますか? – DeiDei

+2

@DeiDei私はそれを覚えていませんが、理由を説明します。 編集:明確にするために、実際には参照だけでなくオブジェクトを作成しています。 – Matt

+0

"一生の延長の一種" - 人生は完了の時に終わります。 - それ以外は何も起こっていないので、あなたは未定義の行動を続けています。 – Soren

答えて

16

Why do gcc and clang allow me to construct an abstract class?

彼らは壊れているので、標準によると。

第10.4節では、抽象クラスの動作を定義します。これは、(C++ 14で)この行が含まれています

no objects of an abstract class can be created except as subobjects of a class derived from it.

ブレース-INIT-リストで参照するための初期設定のルールが一時的に構築し、参照にバインドします。一時的なものはオブジェクトです。したがって、上で書いたコードは、「抽象クラスのオブジェクト」を「それから派生したクラスのサブオブジェクト」以外のものとして作成しようとします。

標準では明白に禁止されているものがあります。この点については、規格にあいまい性はありません。 10.4では、p3は、コンパイラが(関数クラスとして抽象クラスを宣言したり、明示的な変換などを)タイプした場合に、コンパイル時に出力エラーが発生する場所を指定しますが、抽象クラスの構築を禁止する実装が必要です「それから派生したクラスのサブオブジェクト」以外のもの。

一時は「それから派生したクラスのサブオブジェクト」ではありません。コンパイラはこれを禁止する義務があります。

バグのないコンパイラです。

+1

私には右のように見えますが、そのセクションはそれのまわりに何も残っていないようです。 "'' A ':抽象クラスをインスタンス化できないので、少なくとも_all_コンパイラではありません – Matt

+2

@Matt:バグを' gcc'と 'clang'に報告する必要があります。おめでとう! – Destructor

+0

あなたの答えで、OPのコードが未定義の動作IMHOを呼び出すのを忘れてしまった。参照:http://melpon.org/wandbox/permlink/b8w0T43wNxvzeTME。 – Destructor

関連する問題