Frage

Ich erhalte diese Fehlermeldung, wenn sie mit einer Reihe von Klassen einschließlich sie zu tun:

error: expected class-name before '{' token

Ich sehe, was los ist, aber ich weiß nicht, wie richtig es zu korrigieren. Hier ist eine abstrahierte Version des Codes:

A. h

#ifndef A_H_
#define A_H_

#include "K.h"

class A
{
    public:
        A();

};

#endif /*A_H_*/

A.cpp

#include "A.h"

A::A() {}

B.h

#ifndef B_H_
#define B_H_

#include "A.h"

class B : public A
{ // error: expected class-name before '{' token
    public:
        B();
};

#endif /*B_H_*/

B.cpp

#include "B.h"

B::B() : A() {}

J. H

#ifndef J_H_
#define J_H_

#include "B.h"

class J
{
    public:
        J();
};

#endif /*J_H_*/

J.cpp

#include "J.h"

J::J() {}

K.h

#ifndef K_H_
#define K_H_

#include "J.h"

class K : public J
{ // error: expected class-name before '{' token
    public:
        K();
};

#endif /*K_H_*/

K.cpp

#include "K.h"

K::K() : J() {}

main.cpp

#include "A.h"

int main()
{
    return 0;
}

Ab main.cpp , kann ich feststellen, dass das ist, was der Compiler sieht:

#include "A.h"

#ifndef A_H_
#define A_H_

#include "K.h"

#ifndef K_H_
#define K_H_

#include "J.h"

#ifndef J_H_
#define J_H_

#include "B.h"

#ifndef B_H_
#define B_H_

#include "A.h"

class B : public A
{ // error: expected class-name before '{' token

So A 's Definition ist nicht vollständig, wenn wir auf B erhalten. Ich habe gesagt, dass man manchmal eine Vorwärtsdeklaration verwenden müssen, und dann bewegen Sie die #include Anweisung in die CPP Datei, aber ich bin kein Glück haben mit Das. Wenn ich so etwas versuchen, habe ich einfach die zusätzlichen Fehler:

error: forward declaration of 'struct ClassName'

Ich denke, vielleicht bin ich einfach nicht die Dinge an den richtigen Stellen zu tun. Kann mir bitte jemand zeigen, wie dieser Code zu kompilieren? Vielen Dank!


Edit: Ich möchte darauf hinweisen, dass diese nur Version des Real-Code abstrahiert wird. Mir ist klar, dass es keine Hinweise auf K in A oder B in J , aber es gibt in der realen Code, und ich fühle, dass sie völlig erforderlich sind. Vielleicht, wenn ich eine kurze Beschreibung der realen Klassen gibt, kann jemand mir helfen, meinen Code neu strukturieren oder beheben.

Klasse A ist eine abstrakte Knoten-Klasse, die für die Knoten in einem Diagramm als Schnittstelle fungiert. Klasse B ist einer von dem, was eine Reihe von verschiedenen Implementierungen von A sein. In der gleichen Weise, Klasse J ist eine abstrakte Besucherklasse und K ist die entsprechende Umsetzung. Hier ist der Code mit einem wenig mehr Kontext:

A. h (Abstract Node)

#ifndef A_H_
#define A_H_

#include "K.h"

class K;

class A
{
    public:
        A();

        virtual void accept(const K&) const = 0;
};

#endif /*A_H_*/

A.cpp

#include "A.h"

A::A() {}

B.h (Beton Node)

#ifndef B_H_
#define B_H_

#include "A.h"

class K;

class B : public A
{ // error: expected class-name before '{' token
    public:
        B();

        virtual void accept(const K&) const;
};

#endif /*B_H_*/

B.cpp

#include "B.h"

B::B() : A() {}

void B::accept(const K& k) const { k.visit(this); }

J. H (Abstract Visitor)

#ifndef J_H_
#define J_H_

#include "B.h"

class B;

class J
{
    public:
        J();

        virtual void visit(const B*) const = 0;
};

#endif /*J_H_*/

J.cpp

#include "J.h"

J::J() {}

K.h (Concrete Visitor)

#ifndef K_H_
#define K_H_

#include "J.h"

class B;

class K : public J
{ // error: expected class-name before '{' token
    public:
        K();

        virtual void visit(const B*) const;
};

#endif /*K_H_*/

K.cpp

#include "K.h"

K::K() : J() {}

void K::visit(const B*) const {};

main.cpp

#include "A.h"

int main()
{
    return 0;
}

Ich hatte ein paar vorwärts Erklärungen hinzufügen, um einige zusätzliche Fehler zu machen, die erschienen (wenn ich Detail hinzugefügt) weggehen. Einige von ihnen nicht notwendig sein können, oder zu korrigieren.

War es hilfreich?

Lösung

Rund Einschlüsse nicht funktionieren.

Versuchen Einschlüsse auf ein striktes Minimum zu halten. Wenn Sie das tun, werden Sie entweder in Ordnung zusammen sein, oder Sie werden Probleme in Ihrem Design entdecken. In Ihrem Fall sehe ich nichts falsch mit Ihrem Design.

Wenn Klasse K definiert, die Sie nur einen Zeiger auf ein Objekt vom Typ B verwenden, die nicht B erfordern definiert werden (wie in „umfasst die Header-Datei“), nur deklariert werden (Forward-Deklaration ist in Ordnung ). Also, in Ihrem Fall, die Aufnahme zu entfernen, indem ersetzt Header „B.h“ „Klasse B“; ist genügend. (Das gleiche gilt für die Klasse J)

Andere Tipps

Ihr Kopf Einschlüsse sind kreisförmig. A -> K -> J -> B -> A. Vorwärtsdeklarationen zu verwenden ist der einfachste Weg, diese Komplexität zu vermeiden, aber es ist nur möglich, wenn die Klasse verwendet nur Verweis oder Zeiger auf die Klasse ist, enthalten erklärt werden. Sie können keine Erklärung in K.h oder B.h verwenden vorwärts, zum Beispiel, weil sie von J und A erben jeweils. Sie können jedoch die #include "K.h" in A. h mit class K; je nachdem, wie Sie tatsächlich in K mit A werden ersetzen können.

Sprechen Sie

über verwirrend.

In diesem konkreten Beispiel, entfernen Sie die

#include "B.h"

aus der Datei J.h da es ist dort nicht erforderlich. Wenn das nicht funktioniert, benötigen wir noch einige weitere Details darüber, wie J verwendet B ...

Bearbeiten

Da J nur einen Zeiger verwendet, um B, der Rat bleibt gleich :-):

Entfernen #include "B.h" von J.h und ersetzen sie durch eine Vorwärtserklärung B:

(J.h)
class B;

class J
{
  // ...
  virtual void visit(const B*) const = 0; // This will work with forward declaration
}

Auch #include "K.h"from A.h entfernen.

Wichtig

Natürlich müssen Sie die benötigten hinzufügen enthält in den jeweiligen CPP-Dateien:

(J.cpp)
#include "B.h"
// ...
// Go ahead with implementation of J
// ...

(Das Gleiche gilt für A.cpp, umfassen K.h)

Das Hauptproblem ist, dass Ihre Header-Dateien sich in einer kreisförmigen Weise umfassen. A enthält K die J enthält, die B enthält, die A dann wieder schließt ... Sie sollten verlangen nie eine Situation, in der dies geschieht. Sie sollten auf das Design Zeichenbrett zurück gehen und entweder einige der Abhängigkeiten schneiden oder Ihre Klassen völlig neu zu organisieren, so dass diese zirkuläre Abhängigkeit nicht geschieht.

Das Problem ist, dass Ihre Header-Dateien zyklisch voneinander abhängig sind. Nicht K.h in A.h und B.h in J.h umfassen. Sie sind dort nicht erforderlich.

In Bezug auf Ihre bearbeiten: Dies ist nicht der beste Weg für Ihre Objekte zu interagieren. Rethink Ihr Design. Wer ruft node.accept(visitor)? Können Sie nicht visitor(node) direkt anrufen?

Auch, wenn Sie eine Grafik-Bibliothek zu entwerfen sind versuchen, einen Blick auf Boost.Graph Bibliothek.

Wie gesagt, da Sie nur einen Zeiger verwenden, in B J.h, Sie müssen nicht B.h enthalten, nur voraus deklarieren die Klasse.

class B;

struct J
{
    virtual void visit(const B*) const = 0;
};

Dann schließen B.h in Ihrer K.cpp Datei.

#include "K.h"
#include "B.h"

void K::visit(const B* b) const
{
    // use b here any way you want
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top