在类声明/定义中包含标头

时间:2011-09-08 11:04:01

标签: c++

我知道你可以这样做:

def.h:

A();
int x;

A.H

class A
{
public:
#include "def.h"
}

A.cpp

A::A()
{
    x = 0;
}

int main()
{
    A a;
    return 0;
}

我的问题是:你为什么要这样做?有什么好处吗?我可以看到如果你有一些具有相同成员但不是相同基础的类会有什么帮助,但是值得麻烦吗?它不是很易读,是吗? 另外,编译器如何处理这些包含?它只是将标题的内容粘贴到它包含的位置(有点像宏)吗?

5 个答案:

答案 0 :(得分:3)

我从来没有在课堂上看过这个,如果你想在前几天仍然理解这些代码,我会建议你永远不要这样做。

也就是说,有一种情况我发现这种技术是可以接受的,那就是你有一个大表,你需要从中生成多个构造,如枚举和属性表。我们有两个文件,如:

foobars.h:

enum Foobars {
#define FOOBAR(id, description, args) FOOBAR_##id,
#include "foobars.tab"
#undef FOOBAR
};

extern const char *foobar_names[];
const char *parse_foobar(Foobars fb, const char *input);

foobars.cpp:

#include "foobars.h"
const char *foobar_names[] = {
#define FOOBAR(id, description, args) description,
#include "foobars.tab"
#undef FOOBAR
};

const char *parse_foobar(Foobars fb, const char *input) {
    switch(fb) {
#define INT get_int(&input)
#define FLOAT get_float(&input)
#define STRING get_string(&input)
#define FOOBAR(id, description, args) args
#include "foobars.tab"
#undef FOOBAR
    }
return input;

魔法在“foobars.tab”中(它很特别,所以我建议不要调用any.h或anything.hpp或任何其他常见后缀):

/* CAUTION! This file is included using C preprocessor in the middle of various structures
 * It must not contain anything except definitions of foobars in the FOOBAR macro and
 * comments. Don't forget NOT to write semicolons; some of the structures are
 * comma-separated and some semicolon-separated. FOOBAR will be defined appropriately before
 * including this file. */
FOOBAR(NULL, "Empty command, does nothing", {}) // NO semicolon!
// Also some preprocessors don't like empty arguments, so that's why {}.
// (void)0 is an alternative.
FOOBAR(FOO, "Foo bars and bazes", a = INT; b = STRING)
FOOBAR(BAR, "Bars, but does not baz", x = FLOAT)
...

另一种选择是为特殊包含的内容定义宏。如果表很短,则宏更容易阅读,但如果文件很长,则特殊文件更有意义。

最后一个选项是让表格完全不同并生成代码,但这涉及编写一些特殊的脚本来构建它,而这不是。

答案 1 :(得分:2)

在像Ruby这样的语言中,这个概念被称为Mixin。由于我们在C ++中有多重继承,因此我们不需要它。

答案 2 :(得分:1)

预处理器(在任何之前运行),当它偶然发现include时,几乎完全复制该标题的内容并将其粘贴到{{1}的位置指令。

使用它的好处很少,主要的是你不必重复代码。

然而,在9999/10000的情况下,绝对不值得麻烦。如果你在头文件的某个地方有一个拼写错误,你会在每个使用它的文件中出现奇怪的错误,并且在你真正打开文件并阅读它之前,它根本不清楚它在做什么。

如果可能的话,尽量避免。我想不出一个绝对必要的情况;大部分时间都可以通过遗传或组合实现相同的效果而没有任何副作用。

答案 3 :(得分:1)

我发现的一个用法是,如果你想在类定义中自动生成大量的行,那么包含这样的自动生成的文件会很有帮助。

答案 4 :(得分:0)

这些答案都很老,但我找到了上面没有列出的理由。我正在编写自动化测试,需要访问私有成员,因此在许多类中使用友谊声明。 由于友谊不是继承的,我必须在与其交互的每个类中明确声明任何新测试类的友谊。

如果根据“test_friends.h”列出我的测试类的一个或多个文件,这会更容易做到:

friend class testOneFeature;
friend class testAnotherFeature;

等,在测试类中,我可以简单地在声明中包含该文件。

class MyClass
{
#include "test_friends.h"
public:
 //etc 
};