Frage

Kann jemand erklären, warum der folgende Code nicht kompiliert (auf 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);
}

Die Nachricht, die ich bekomme, lautet:

JJJ.CPP: In der Funktion 'int main ()':
JJJ.CPP: 10: 'xx :: a' ist kein statisches Mitglied von 'Struct X'
JJJ.CPP: 10: Keine Übereinstimmungsfunktion für Anruf unter 'x :: x ()' ''
JJJ.CPP: 1: Kandidaten sind: x :: x (const x &)
jjj.cpp: 5: x :: x (x :: state) `

Ist dieser schlechte Code oder ein Compiler -Fehler?

Problem gelöst von Neil+Konrad. Siehe die Kommentare zu Neils Antwort unten.

War es hilfreich?

Lösung

X(X::A);

wird ASA -Funktionserklärung gesehen. Wenn Sie diesen Code wirklich wollen, verwenden Sie:

(X)(X::A);

Andere Tipps

Sie haben den variablen Namen in Ihrer Definition vergessen:

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

Ihr Code verwirrt den Compiler, da er syntaktisch nicht von einer Funktionserklärung unterscheiden kann (Rückkehr X und vorübergehen X::A als Argument). Im Zweifelsfall ist der C ++ - Compiler immer zugunsten einer Erklärung an.

Die Lösung besteht darin, redundante Klammern um die einzuführen X Da der Compiler Klammern um Typen verbietet (im Gegensatz zu Konstruktionsaufrufen usw.):

(X(X::A));

Nur um es kristallklar zu machen, was passiert. Sehen Sie sich dieses Beispiel an

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

Was wird es ausgeben? Nun, es wird ausgeben 0. Das int(a) von oben kann auf zwei verschiedene Arten analysiert werden:

  • Wirken Sie das Ergebnis an und verwerfen Sie das Ergebnis
  • Deklarieren Sie eine Variable genannt a. Aber ignorieren Sie die Klammern um die Kennung.

Der Compiler, wenn eine solche Situation erscheint, in der ein Funktionsbetrieb in einer Erklärung verwendet wird und sie auch wie eine Erklärung aussieht, wird sie immer als Erklärung betrachten. Wenn es nicht syntaktisch eine Erklärung sein kann (der Compiler wird die gesamte Linie betrachten, um dies zu bestimmen), wird es als Ausdruck angesehen. Somit weisen wir uns dem inneren zu a Oben die Außen a bei Null.

Jetzt ist Ihr Fall genau das. Sie versuchen (versehentlich), eine Kennung namens zu deklarieren A Innerhalb einer Klasse genannt X:

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

Der Compiler stöhnt dann über einen nicht deklarierten Standardkonstruktor, da der Statische, wie er annimmt, standardmäßig konstruiert ist. Aber selbst wenn Sie einen Standardkonstruktor für X hatten, ist er natürlich immer noch falsch, weil auch nicht A ist ein statisches Mitglied von X, noch eine Statik von X kann im Blockbereich definiert/deklariert werden.

Du kannst es schaffen nicht Sieh wie eine Erklärung aus, indem du mehrere Dinge mache. Erstens können Sie den gesamten Ausdruck erfassen, was es nicht mehr wie eine Erklärung aussehen lässt. Oder einfach den Typ, der gegossen wird. Beide Disamiguationen wurden in anderen Antworten erwähnt:

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

Es gibt eine ähnliche, aber eindeutige Mehrdeutigkeit, wenn Sie versuchen, tatsächlich ein Objekt zu deklarieren. Sehen Sie sich dieses Beispiel an:

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

Da int(a) Kann sowohl die Deklaration eines Parameters sein, der genannt wird a und die explizite Umwandlung (gegossen) des Float-Variable in einen int, der Compiler entscheidet erneut, dass dies eine Erklärung ist. Daher deklarieren wir zufällig eine Funktion genannt b, was ein ganzzahliges Argument nimmt und eine Ganzzahl zurückgibt. Es gibt mehrere Möglichkeiten, wie Sie dies auf der Grundlage der oben genannten Disambiguation durchführen können:

int b((int(a))); int b((int)a);

Sie sollten ein Objekt als Objekt deklarieren als

X x(X::A);

Fehler in Ihrem Code.

Eine dieser beiden Zeilen funktioniert für mich:

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

Wie Neil Butterworth betont, X(X::A) wird als Funktionserklärung behandelt. Wenn Sie wirklich ein anonymer Objekt wollen, (X)(X::A) Erstellt ein X -Objekt und löscht es sofort.

Sie könnten natürlich so etwas tun:

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

Dies wäre lesbarer und hat im Grunde den gleichen Effekt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top