包含在C ++应用程序中的头文件顺序

时间:2014-06-03 18:08:35

标签: c++ circular-dependency undefined-reference

是否有软件/工具可以查看编译C ++应用程序后包含头文件的顺序?我发现自己经常遇到循环依赖问题并看到“未定义的引用”错误消息:(

更新#1

我熟悉标题包括警卫,我正在使用它们,但由于某种原因,我仍然遇到循环依赖问题。

在我的情况下,我有很多情况, A类使用 B类,反之亦然。在这些情况下,我在 A.h 的顶部使用前向声明,例如“ B类; ”,反之亦然。

我是否需要在 A.h 的顶部做“ #include”B.h“”?或者“ B类; ”在 A.h 的顶部是否足够?

更新#2

您好,下面是我编译/链接时遇到问题的代码片段。下面有3个类:

A.cpp

#include "A.h"

namespace sef
{
    A::A() {
        // TODO Auto-generated constructor stub
        b = 0;
    }

    A::~A() {
        // TODO Auto-generated destructor stub
    }

    bool A::execute()
    {
        C::connectAndSaveFile();
        b->start();
        return true;
    }
}

A.H

#ifndef A_H_
#define A_H_

//#include "B.h"
class B;
#include "C.h"

namespace sef {

    class A {
    public:
        B* b;
        bool execute();

        A();
        virtual ~A();
    };

}

#endif /* A_H_ */

B.cpp

#include "B.h"

B::B() {
    // TODO Auto-generated constructor stub
    engine = 0;
    bool result = engine->execute();
    cout << result << endl;
}

B::~B() {
    // TODO Auto-generated destructor stub
}

void B::start()
{

    cout << "B::start()" << endl;
}

B.h

#ifndef B_H_
#define B_H_

#include <iostream>
#include <string>
using namespace std;

//#include "A.h"

namespace sef {
    class A;
}

class B
{
public:
    sef::A* engine;

    B();
    virtual ~B();
    void start();
};

#endif /* B_H_ */

C.cpp

#include "C.h"

C::C() {
    // TODO Auto-generated constructor stub

}

C::~C() {
    // TODO Auto-generated destructor stub
}

void C::connectAndSaveFile()
{
    cout << "C::connectAndSaveFile()" << endl;
}

C.h

#ifndef C_H_
#define C_H_

#include <iostream>
#include <string>
using namespace std;

class C {
public:
    C();
    virtual ~C();

    static void connectAndSaveFile();
};

#endif /* C_H_ */

我似乎得到了错误:

***g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\A.o" "..\\src\\A.cpp" 
..\src\A.cpp: In member function 'bool sef::A::execute()':
..\src\A.cpp:23:4: error: invalid use of incomplete type 'class B'
In file included from ..\src\A.cpp:7:0:
..\src\A.h:12:7: error: forward declaration of 'class B'***

1 个答案:

答案 0 :(得分:2)

您的前向声明是一个良好的开端,但此外,A.cpp将需要包括B.h和C.h,因为它取消引用B*并在C中调用静态函数。同样,B.cpp需要A.h,因为它取消引用A*。可能还有其他问题,但这应该让你走上正轨。

长话短说,class A的前向声明只告诉编译器A是类的名称。这足以让您在说出A*A&(或其他几件事)时知道您的意思,但如果您想在A上实际调用函数,或访问成员变量,或按值返回/取A,或者使用A 1 类型的变量,您需要A的完整定义从它的标题。

1 基本上,任何需要编译器知道sizeof(A)或其成员/祖先信息的操作。


此外,这不是您的问题,但此代码将为您提供未定义的行为:

B::B() {
    // TODO Auto-generated constructor stub
    engine = 0;
    bool result = engine->execute();
    cout << result << endl;
}

您有效地将engine设置为null,然后在其上调用函数。

除了最初的主题之外,通常认为头文件中的using namespace std是不好的做法,因为包含它的每个人都将被迫使用该命名空间,无论他们是否愿意。