2016-05-06 5 views
7

私はなぜこのような奇妙な問題が発生しているのですか?第三にはないながら、第一次のコードスニペットの第二は、コンパイル:パラメータとしてプライベートネストされた型を使用する

はコンパイル:

class Foo { 
public: 
    Foo() { Bar(); } 

private: 
    class Bar {}; 
}; 

はコンパイル:

class Foo { 
    class Bar {}; // Or only forward declare here and define later 

public: 
    Foo(Bar) {} 
} 

はコンパイルされません

class Foo { 
public: 
    Foo(Bar) {} 

private: 
    class Bar {}; 
}; 

最初のことができている間に3番目のものがコンパイルに失敗するのは何ですか?

+0

うわーを。オプション3は、VS2015のコンパイラが死んでしまう。コンパイラが頻繁にクラッシュするのを見ないでください。 – user4581301

+0

とにかく、 'Foo'3のコンストラクタは' Foo :: Bar'を提供しなければならず、プライベートなのでできません。これは、このコードを不整合な状態にします。それはコンパイルされませんが、ルールを引用することはできません。しかし、なぜ2番目のものがコンパイルされますか? 'Bar'もプライベートになりますが、' Foo'コンストラクタの前に定義されます。 – user4581301

答えて

4

通常、C++では、以前に翻訳単位で行った宣言のみ参照できます。しかし、クラス定義の中で、メンバ関数の定義は、クラスの後半で行われる宣言の参照を許可されています。基本的に、コンパイラは、クラスの直後に記述されているかのように動作するように、クラス定義を再構築します。

しかし、これは関数定義にのみ当てはまります。関数の宣言(パラメータ型を含む)はこれを行うことができません。すでにファイル順で宣言された宣言のみ参照できます。

だから、これを行うことができます:

class Test 
{ 
    public: 
     void Func(int x) {Inner foo;} 

    private: 
     class Inner {}; 
}; 

ではなく、この:

class Test 
{ 
    public: 
     void Func(Inner x) {} 

    private: 
     class Inner {}; 
}; 
+2

つまり、ボディには完全な可視性がありますが、メソッド定義には表示されません。そして、これは私が愚か者のように感じるようにする[私は今朝これを読む。](http://stackoverflow.com/questions/37079271/declaring-class-variables-after-assigning-them-values-in-c) – user4581301

2

最初の例では、private Barについては何も公開していませんが、3番目の例では外部に公開していません。

第3の例は、Barという単一の引数を持つコンストラクタを持ついくつかのクラスFooが存在すると言っています。しかし、Barは外部には不明です。そのようなコンストラクタを呼び出すと想像してください。

おそらくFoo::Barにアクセスできません。

+1

これも私の考えですが、 'Foo'バージョン2がどのようにコンパイラからのパスを得るのか説明していません。 – user4581301

関連する問題