4

次のコードがコンパイルされない理由を誰かが説明できますか(g ++(GCC)3.2.3 20030502(Red Hat Linux 3.2.3-49))?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

私が受け取るメッセージは次のとおりです。

jjj.cpp:関数内'int main()':
jjj.cpp:10:'XX ::A'は'structX'の静的メンバーではありません
jjj.cpp:10:'Xの呼び出しに一致する関数がありません: :X()'
jjj.cpp:1:候補は次のとおりです:X :: X(const X&)
jjj.cpp:5:X :: X(X :: State) `

これは悪いコードですか、それともコンパイラのバグですか?

Neil+Konradによって解決された問題。以下のニールの答えへのコメントを参照してください。

4

6 に答える 6

10

定義の変数名を忘れました:

int main()
{
   X my_x(X::A);
}

構文的にはこれを関数宣言(引数として返しXたり渡したりする)と区別できないため、コードはコンパイラを混乱させます。X::A疑わしい場合は、C++コンパイラは常に宣言を優先して明確にします。

X解決策は、コンパイラが型の周りの括弧を禁止しているため(constructo呼び出しなどとは対照的に)、冗長な括弧を導入することです。

(X(X::A));
于 2009-03-25T13:16:58.850 に答える
8
X(X::A);

関数宣言として見られています。このコードが本当に必要な場合は、次を使用してください。

(X)(X::A);
于 2009-03-25T13:17:25.683 に答える
1

何が起こるかを明確にするためだけに。この例を見てください

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

何を出力しますか?まあ、それは出力されます0。上記のint(a)は、次の 2 つの異なる方法で解析できます。

  • int にキャストして結果を破棄する
  • という変数を宣言しますa。ただし、識別子を囲む括弧は無視してください。

関数スタイルのキャストがステートメントで使用され、宣言のようにも見えるような状況が発生した場合、コンパイラは常にそれを宣言として受け取ります。構文的に宣言できない場合 (コンパイラーはそれを判断するために行全体を調べます)、それは式であると見なされます。したがって、上の内側に代入しa、外側aをゼロのままにします。

今、あなたのケースはまさにそれです。Aと呼ばれるクラス内で呼び出される識別子を(誤って)宣言しようとしていますX

X (X::A); // parsed as X X::A;

コンパイラーは、宣言されていないデフォルトコンストラクターについてうめき声を上げます。これは、静的であることを前提として、デフォルトで構築されているためです。しかし、X のデフォルト コンストラクターがあったとしてAも、X の静的メンバーでもなく、ブロック スコープで X の静的を定義/宣言することもできないため、もちろん間違っています。

いくつかのことを行うことで、宣言のように見えないようにすることができます。まず、式全体を括弧で囲むことができます。これにより、宣言のように見えなくなります。または、キャスト先の型を括弧で囲みます。これらの明確化は両方とも、他の回答で言及されています。

(X(X::A)); (X)(X::A)

オブジェクトを実際に宣言しようとすると、似ていますが明確なあいまいさが生じます。この例を見てください:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

int(a)呼び出されるパラメーターの宣言と、float 変数の int への明示的な変換 (キャスト) の両方が可能なためa、コンパイラーはそれが宣言であると再度​​判断します。bしたがって、整数の引数を取り、整数を返す という関数をたまたま宣言します。上記の曖昧さ回避に基づいて、それを明確にする方法がいくつかあります。

int b((int(a))); int b((int)a);
于 2009-03-25T17:42:16.153 に答える
0

オブジェクトを次のように宣言する必要があります

X x(X::A);

コードのバグ。

于 2009-03-25T13:17:51.407 に答える
0

これらの2つの行のいずれかが機能します:

X obj(X::A);
X obj2 = X(X::A);

Neil Butterworth が指摘するようにX(X::A)、関数宣言として扱われています。本当に無名オブジェクトが必要な場合は(X)(X::A)、X オブジェクトを作成し、すぐに削除します。

于 2009-03-25T13:26:00.093 に答える
0

もちろん、次のようなこともできます。

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

これは読みやすく、基本的に同じ効果があります。

于 2009-03-25T14:09:57.943 に答える