17
  1. 驚いたことに、C++ オブジェクトの名前がクラス名と同じになる可能性があることがわかりました。誰かが私にその理由を説明できますか?
  2. クラスのオブジェクトをaとして宣言するa a1()と、エラーは発生しませんが、コンストラクターは呼び出されません。なぜこうなった?

私のコード:

#include<iostream>
using namespace std;

class a 
{
    public:
    a() 
    {
        cout << "in a\n";
    }
};

int main()
{
    a a1();
    a a;
}
4

5 に答える 5

8

a a1();関数宣言です。

これが、C++11 で一様な初期化が作成された重要な理由です。C++11 でコンストラクターを使用してオブジェクトを初期化するには、次を使用します。a a1{};

于 2013-10-08T14:38:53.683 に答える
4

実際、 C++ ドラフトの標準セクションの 3.3.10 名前の非表示の段落2を見ると、変数を使用してクラスの名前を非表示にすることは有効です(強調鉱山):

クラス名 (9.1) または列挙名 (7.2) は、同じスコープで宣言された変数、データ メンバー、関数、または列挙子の名前によって非表示にすることができます。クラスまたは列挙名と、変数、データ メンバー、関数、または列挙子が同じスコープで (任意の順序で) 同じ名前で宣言されている場合、クラスまたは列挙名は、変数、データ メンバー、関数、または列挙子名が表示されます。

それは良い習慣ではないと思いますし、コードの保守が難しくなるでしょう。このコード行は、実際には関数を宣言しています。

a a1();

代わりに、この pre -C++11を使用することもできます:

a a1 ;

またはC++11で導入された一様な初期化:

a a1{} ;

名前の非表示に戻るとclang、設定されている警告レベルに関係なく、このコードでこれについて警告することに驚きました。

int main()
{
   a a;
   a a2 ;
}

次のメッセージが表示されます。

main.cpp:12:10: note: class 'a' is hidden by a non-type declaration of 'a' here
   a a;
     ^

から同様の警告を取得することはできませんがgcc

アップデート

以前に統一初期化の疣贅について行ったこのコメントについて考えてみると、それa1がどういうわけか正しいタイプではないのではないかと疑っていた場合、 typeidを使用して何が起こっているのかをデバッグできたことに気付きました。たとえば、このコード:

std::cout << typeid(a).name() << std::endl ;
std::cout << typeid(a1).name() << std::endl ;

Coliru live exampleで次の出力が得られます。

1a
F1avE

これをc++filtに渡すと、次の出力が得られます。

a ()     // A function that returns type a
a        // type a
于 2013-10-08T14:41:40.453 に答える
0

これは、 でコンパイルしようとしたときにコードから取得したclangものです。すべてを表していると思います。

test.cpp:15:9: warning: empty parentheses interpreted as a function declaration
      [-Wvexing-parse]
    a a1();
        ^~
test.cpp:15:9: note: remove parentheses to declare a variable
    a a1();
        ^~
1 warning generated.
于 2013-10-19T13:09:09.253 に答える
0

a a1();a呼び出しコンストラクターとは関係のない関数宣言の戻り値の型です

a a ;単純なステートメントは正常に機能し、コンストラクターを呼び出します

于 2013-10-08T14:35:11.533 に答える