1

晚上好 :)

我在玩 g++ 和 makefile。我已经到了这一点:

富.h:

#ifndef _FOO_H_
#define _FOO_H_

#include "bar.h"

class foo {
private:
    bar something;
public:
    bool start();
    bool stop();
};

#endif // _FOO_H_

Foo.h 最终包含在我的主 cpp 文件中,因此我可以通过调用 start/stop 来启动。

void somewhere() {
    foo* hihi = new foo;
    hihi->start();
    delete hihi;
}

然后是bar.h:

#ifndef _BAR_H_
#define _BAR_H_

class bar {

};

#endif // _BAR_H_


但是 g++ 似乎不喜欢它:

g++  (some_flags) -c main.cpp
In file included from main.cpp:2:
foo.h:8: error: ‘bar’ does not name a type

我正在使用makefile,并尝试了以下组合:

main.o: main.cpp foo.h bar.h

尽管我认为我不应该在这里添加 bar.h,但不应该将它包含在 foo.h 中就足够了吗?

为了澄清,这大致是它现在的设置方式(是的,我知道这可以以更有效的方式完成):

main.o: main.cpp foo.h
    $(CC) $(CFLAGS) -c main.cpp

foo.o: foo.h foo.cpp
    $(CC) $(CFLAGS) -c foo.cpp

bar.o: bar.h bar.cpp
    $(CC) $(CFLAGS) -c bar.cpp

这是怎么回事?我认为这是我对 g++ 及其处理标头的方式所缺少的东西,请指出正确的方向!

编辑 - 找到解决方案:

嗬!我现在觉得很傻。正在搞乱 boost::asio 并且有点忘了我仍然把它留在我的标题顶部的某个地方:使用 boost::asio::ip::tcp;

假设有一个 boost::asio::ip::tcp::bar 函数:D

哦,好吧,还是谢谢!

4

4 回答 4

2

仔细检查一切。如果包含bar.hinto foo.h,编译器不应引发错误。你包括foo.hbar.h吗?最好不要这样做,因为这会导致标题之间的循环依赖,这将导致那种错误。

还要检查头部防护的拼写。这可能是一个常见的烦恼来源:

#ifdef _BAR_H_ // OOPS! we wanted #ifndef
#define _BAR_H_

class bar {

};

#endif // _BAR_H_

此外,您应该避免在标题保护宏名称之前放置下划线。这些名称保留给编译器。打电话INCLUDED_BAR_H或只是BAR_H_代替。

于 2009-03-22T04:23:22.357 回答
2

正在搞乱 boost::asio 并且有点忘了我仍然把它留在我的标题顶部的某个地方:使用 boost::asio::ip::tcp;

假设有一个 boost::asio::ip::tcp::bar 函数

Dan Saks 解释了为什么应该 typedef 类名的一些原因,即使它看起来是多余的。

好吧,您已经遇到了现实生活中的情况,在这种情况下,定义一个类可能会帮助您更轻松地找到您的问题:

 class bar {
 // ...
 };
 typedef class bar bar;

bar()如果已经声明了一个名为的函数,则生成这个更有意义的消息:

In file included from C:\temp\foo.h:4,
                 from C:\temp\test.cpp:4:
C:\temp\bar.h:7: error: `typedef class bar bar' redeclared as different kind of symbol
C:\temp\test.cpp:1: error: previous declaration of `void bar(int)'
C:\temp\bar.h:7: error: declaration of `typedef class bar bar'
于 2009-03-22T04:48:25.510 回答
1

Tommy Hui 和 litb 已经指出了两个可能的原因;这里有一些背景信息,希望能派上用场。

首先,这与makefile 无关。makefile 只是一个方便的东西,它为你调用 g++,仅此而已。

这些带有头文件的东西起初可能有点难以理解,尤其是当你陷入循环依赖时。它确实帮助我意识到了这三件事:

  • A#include只不过是一个复制/粘贴操作,在该点插入包含文件的内容。
  • 一切都必须在使用前声明。有时,当循环依赖出现时,您可能需要class bar;在另一个头文件中预先声明一个类(例如)。
  • 如果在使用时需要关于类型的更多信息而不仅仅是它的存在,那么还需要类型的定义。这适用于调用该类型对象的方法,也适用于包含该类型的字段!(但不适用于指向该类型对象的指针,因为指针的大小都相同。)
于 2009-03-22T04:25:03.350 回答
0

在 main.cpp 中,您需要在文件顶部添加以下行:

#include "foo.h"
于 2009-03-22T04:17:23.447 回答