在处理多个类(包括彼此)时,我收到此错误:

error: expected class-name before '{' token

我看到发生了什么事,但我不知道如何正确纠正它。这是代码的抽象版本:

#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() {}

小时

#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() {}

主程序

#include "A.h"

int main()
{
    return 0;
}

开始于 主程序, ,我可以确定这是编译器看到的:

#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

所以, A当我们到达时, 的定义还不完整 . 。有人告诉我,有时您需要使用前向声明,然后移动 #包括 声明进入 .cpp 文件,但我对此没有任何运气。如果我尝试类似的操作,我只会收到额外的错误:

error: forward declaration of 'struct ClassName'

我想也许我只是没有在正确的地方做事。有人可以告诉我如何编译这段代码吗?非常感谢!


编辑:我想指出,这只是真实代码的抽象版本。我意识到没有任何参考 KA 或者 J, ,但是在真实的代码中是有的,我觉得它们是完全必要的。也许如果我对真实的类进行简要描述,有人可以帮助我重组或修复我的代码。

班级 A 是一个抽象节点类,充当图中节点的接口。班级 是许多不同实现之一 A. 。同样的方式,班级 J 是一个抽象的 Visitor 类并且 K 就是对应的实现。这是带有更多上下文的代码:

(抽象节点)

#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 (具体节点)

#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 (摘要访客)

#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() {}

小时 (具体访客)

#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 {};

主程序

#include "A.h"

int main()
{
    return 0;
}

我必须添加一些前向声明,以使出现的一些其他错误(当我添加详细信息时)消失。其中一些可能不是必要的或不正确的。

有帮助吗?

解决方案

圆形的夹杂物不工作。

尽量保持夹杂物控制在最小值。如果你这样做,你要么被罚款完全,或者你会发现在你的设计问题。在你的情况,我看不出有什么不对您的设计。

当定义类K,你只使用一个指针到类型B的一个目的即不需要B到被定义(如“包含头文件”)中,仅被宣布(向前声明是细)。所以,在你的情况下,删除列入标题“B.h”改为“B类”;足够了。 (这同样适用类J)的

其他提示

您头夹杂物是圆形的。 A - >的K - >的J - >乙 - > A.使用前向声明是为了避免这种复杂性的最简单的方法,但所声明的类时,只使用引用或指针被包含在类只可能。你不能在K.h或B.h使用前声明,例如,因为他们自J和A分别继承。但是,你可以根据你如何在实际使用#include "K.h"class K; K更换A在A.H。

谈论混乱。

在本具体例中,删除

#include "B.h"

从文件J.h因为它不是需要在那里。如果不行,我们就需要约J如何使用B一些更多的细节......

修改

由于J仅使用一个指针B,建议保持不变:-):

#include "B.h"删除J.h和由B的前向声明替换:

(J.h)
class B;

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

另外除去#include "K.h"from A.h

重要

当然需要添加所需的包括在各个相应CPP文件:

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

(同为A.cpp,包括K.h

的主要问题是,你的头文件包括彼此以圆形方式。一个包括K个,其中包括j,它包括B-然后包括再......你不应该要求的情况下发生这种情况。你应该回到设计画板要么削减一些依赖,或者完全重新组织类,以便该循环依赖不会发生。

问题在于您的头文件循环相互依赖。不包括 K.hA.hB.hJ.h. 。那里不需要他们。

关于您的编辑:这不是对象交互的最佳方式。重新思考你的设计。谁打电话 node.accept(visitor)?你不能打电话吗 visitor(node) 直接地?

另外,如果您想设计一个图形库,请看看 Boost.Graph 图书馆。

也就是说,因为您只使用一个指针 BJ.h, ,你不必包括 B.h, ,仅前向声明该类。

class B;

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

然后包括 B.h 在你的 K.cpp 文件。

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

void K::visit(const B* b) const
{
    // use b here any way you want
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top