C++棘手的继承类定义问题

Sco*_*ott 1 c++ inheritance forward-declaration

在处理包括彼此在内的多个类时,我遇到了这个错误:

error: expected class-name before '{' token
Run Code Online (Sandbox Code Playgroud)

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

#ifndef A_H_
#define A_H_

#include "K.h"

class A
{
    public:
        A();

};

#endif /*A_H_*/
Run Code Online (Sandbox Code Playgroud)

A.cpp

#include "A.h"

A::A() {}
Run Code Online (Sandbox Code Playgroud)

BH

#ifndef B_H_
#define B_H_

#include "A.h"

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

#endif /*B_H_*/
Run Code Online (Sandbox Code Playgroud)

B.cpp

#include "B.h"

B::B() : A() {}
Run Code Online (Sandbox Code Playgroud)

JH

#ifndef J_H_
#define J_H_

#include "B.h"

class J
{
    public:
        J();
};

#endif /*J_H_*/
Run Code Online (Sandbox Code Playgroud)

J.cpp

#include "J.h"

J::J() {}
Run Code Online (Sandbox Code Playgroud)

KH

#ifndef K_H_
#define K_H_

#include "J.h"

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

#endif /*K_H_*/
Run Code Online (Sandbox Code Playgroud)

K.cpp

#include "K.h"

K::K() : J() {}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include "A.h"

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp开始,我可以确定这是编译器看到的:

#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
Run Code Online (Sandbox Code Playgroud)

所以,当我们到达B时,A的定义并不完整.我被告知有时你需要使用前向声明,然后将#include语句移动到.cpp文件中,但我没有运气.如果我尝试这样的话,我只会得到额外的错误:

error: forward declaration of 'struct ClassName'
Run Code Online (Sandbox Code Playgroud)

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


编辑:我想指出这只是真实代码的抽象版本.我认识到,没有引用ķ一个Ĵ,但在真正的代码,我觉得他们是完全必要的.也许如果我简要介绍一下真正的类,有人可以帮我重组或修改我的代码.

是一个抽象类节点充当用于在图中的节点的接口.B类是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_*/
Run Code Online (Sandbox Code Playgroud)

A.cpp

#include "A.h"

A::A() {}
Run Code Online (Sandbox Code Playgroud)

Bh(具体节点)

#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_*/
Run Code Online (Sandbox Code Playgroud)

B.cpp

#include "B.h"

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

void B::accept(const K& k) const { k.visit(this); }
Run Code Online (Sandbox Code Playgroud)

Jh(抽象访客)

#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_*/
Run Code Online (Sandbox Code Playgroud)

J.cpp

#include "J.h"

J::J() {}
Run Code Online (Sandbox Code Playgroud)

Kh(具体访客)

#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_*/
Run Code Online (Sandbox Code Playgroud)

K.cpp

#include "K.h"

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

void K::visit(const B*) const {};
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include "A.h"

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我不得不添加一些前向声明来使一些额外的错误(当我添加细节时)消失.其中一些可能没有必要或正确.

Sim*_*ead 6

您的标题包含是圆形的.A - > K - > J - > B - > A.使用前向声明是避免这种复杂性的最简单方法,但只有当声明的类仅使用对包含的类的引用或指针时才有可能.例如,您不能在Kh或Bh中使用前向声明,因为它们分别从J和A继承.但是,根据您实际使用的方式,您可能可以替换#include "K.h"Ah 中的.class K;KA

谈论混乱.