8

このコードは、(少なくとも)MSVC、ICC、およびGCCによって拒否されます。

class A {
public:
    A( int ) {  }
};

class B: virtual public A {
public:
    //B(): A( -1 ) {  } // uncomment to make it compilable
    virtual void do_something() = 0;
};

class C: public B {
public:
    C(): A( 1 ) {  }
    virtual void do_something() {  }
};

int main() {
    C c;
    return 0;
}

に基づいて

error : no default constructor exists for class "A"
    class B: virtual public A {
                            ^
            detected during implicit generation of "B::B()" at line 14

質問:

  1. コードが実際に無効である場合、これは標準からどの程度正確に準拠していますか?AFAICT、10.4/2と1.8/4を合わせると、Bは最も派生したクラスのタイプにはなり得ないため、12.6.2 / 10以降、BはAのコンストラクターを呼び出すことができなくなります。(セクション番号はC ++ 11用です。)

  2. コードが有効な場合、コンパイラーは、呼び出すことができなかったコンストラクターの存在を要求することにより、標準に違反していますか?彼らはB::B()からA :: A()を呼び出したいだけでなく、 C :: C()のコンパイル中にそれを実行したいことに注意してください(ダブルストレンジ)。

PSこれは元々ICCフォーラムで質問されましたが、このコンパイラに限定されていないため(詳細は発表されません)、ここに投稿されました。

4

3 に答える 3

5

Clang は次のようにエラーを表示します。

error: call to implicitly-deleted default constructor of 'B'
    C(): A( 1 ) {  }
    ^

12.1/5 には、「クラス X のデフォルトのデフォルト コンストラクターは、[...] いずれかの [...] 仮想基底クラス [...] にクラス タイプ M [...] および [...] がある場合、削除されたものとして定義されます。 ] M にはデフォルトのコンストラクターがありません [...]."

于 2012-07-27T18:52:42.860 に答える
3

標準に見られる事実から「定理」を導出しようとしていると思いますが、その「定理」の存在を標準が認めることを期待しています。標準はそれをしません。標準テキストから導き出される可能性のあるすべての「定理」を見つけて組み込むことを目指しているわけではありません。

あなたの「定理」は完全に有効です(何かが欠けていない限り)。クラスBは抽象的であるため、このクラスを最派生クラスとして使用することはできません。これはすぐに、クラスBがその仮想ベースを構築する機会を得られないことを意味しAます。つまり、技術的には、コンパイラは、他の仮想ベース内または他の仮想ベース内Bの適切なコンストラクターの可用性やアクセシビリティを気にする必要はありません。A

しかし、標準は単にその接続を作成せず、作成することを気にしません. 抽象クラスのコンストラクターを特別な方法で処理することはありません。このようなコンストラクターに課せられる要件は、非抽象クラスの場合と同じです。

標準委員会への可能な改善としてそれを提案してみることができます。

于 2012-07-27T19:06:19.770 に答える
0

12.6.2/4ではこれが禁止されているようです。

特定の非静的データメンバーまたは基本クラスがmem-initializer-idによって指定されていない場合(コンストラクターにctor-initializerがないためにmem-initializer-listがない場合を含む)、

—エンティティが(おそらくcv修飾された)クラスタイプ(またはその配列)または基本クラスの非静的データメンバーであり、エンティティクラスが非PODクラスである場合、エンティティはデフォルトで初期化されます(8.5)。 。

クラスが仮想ベースであるかどうかに関係なく、Bデフォルトのコンストラクターはコンパイラーによって合成され、そのようなデフォルトのコンストラクターはそのAベースを構築する方法を知らないように見えます(「エンティティはデフォルトで初期化されます(8.5) ")。

于 2012-07-27T18:58:04.213 に答える