親の初期化が機能するのに、コンストラクタ初期化リストのC ++ 11中括弧の初期化が機能しないのはなぜですか?

oryan_dunn

コンストラクタ初期化リストの{}初期化は、抽象型への参照を初期化するときの()初期化とどのように異なりますか?以下のクラスバーをご覧ください。

class AbstractBase
{
public:
    AbstractBase() {}
    virtual ~AbstractBase() = default;

    virtual void ab() = 0;
};

class Foo : public AbstractBase
{
public:
    Foo() {}

    void ab() {}
};

class Bar
{
public:
    Bar(const AbstractBase& base) : myBase{base} {}

private:
    const AbstractBase& myBase;
};


int main()
{
    Foo f{};
    Bar b{f};

}

コンパイルするとエラーが発生します

test5.cpp: In constructor ‘Bar::Bar(const AbstractBase&)’:
test5.cpp:22:48: error: cannot allocate an object of abstract type ‘AbstractBase’
     Bar(const AbstractBase& base) : myBase{base}
                                                ^
test5.cpp:2:7: note:   because the following virtual functions are pure within ‘AbstractBase’:
 class AbstractBase
       ^
test5.cpp:8:18: note:   virtual void AbstractBase::ab()
     virtual void ab() = 0;

行を変更する

Bar(const AbstractBase& base) : myBase(base) {}

コンパイルして正常に実行されます。

StroustrupのC ++ 11の本を読んで、std :: initializer_list <>をとるコンストラクターと他のコンストラクターとの間にあいまいさがあった場合を除いて、ほとんどすべての場合で{}は()と同じであるという印象を受けました。タイプとしてautoを使用している場合、どちらもここでは実行していません。

んん

簡単な答え:これはC ++ 14で修正された標準のバグであり、g ++ 4.9で修正されています(C ++ 11モードにも遡及的に適用されます)。欠陥レポート1288


より簡単な例を次に示します。

struct S
{
    int x;
    S() { }     // this causes S to not be an aggregate (otherwise aggregate 
                // initialization is used instead of list initialization)
};

S x = 5;
S const &y { x } ;    

x = 6;
std::cout << y << std::endl;     // output : 5

C ++ 11のテキストでは、の意味は;S const &y {x};にバインドyないことxです。実際の意味は、一時的なものを作成し、それに参照をバインドすることです。C ++ 11 [dcl.init.ref] / 3から:

それ以外の場合、Tが参照型の場合、Tによって参照される型の一時的なprvalueがリストで初期化され、参照はその一時的なものにバインドされます。[注:参照型が非const型への左辺値参照である場合、通常どおり、バインディングは失敗し、プログラムは不正な形式になります。—エンドノート]

これはかなりばかげています。明らかに、このコードの目的はにy直接バインドすることxです。C ++ 14では、テキストが変更されました。

それ以外の場合、初期化子リストにタイプEの単一要素があり、Tが参照型ではないか、その参照型がEに参照関連している場合、オブジェクトまたは参照はその要素から初期化されます。

型はそれ自体(またはその基本クラスの1つ)に参照関連しているため、ここのサンプルと実際のコードでは、実際に正しくバインドする必要があります。


エラーメッセージは、C ++ 11の文言に従いbase、参照をバインドするための一時的なfrom作成しようとしているコンパイラから送信されます。baseは抽象型であるため、これは失敗します

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ