在类声明/定义中包含头文件
Including headers inside class declaration / definition
我知道你可以这样做:
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;
}
我的问题是:你为什么要这样做?有什么好处吗?我可以看到,如果你有一些类有相同的成员,但不是相同的基础,这将是有帮助的,但它值得的麻烦吗?这不是很好读,是吗?此外,编译器如何处理这些包含?它只是粘贴标题的内容,其中包括(有点像一个宏)?
我从来没有在一个类中看到过这种情况,如果你想在另一天仍然理解代码,我建议你永远不要这样做。
也就是说,有一种情况,我发现这种技术是可以接受的,那就是当您有一个大表,您需要从中生成多个结构,如枚举和属性表。让我们有两个文件,如:
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"。(它很特殊,所以我建议不要将其命名为anything.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)
...
另一个选择是定义一个宏来包含特殊的内容。如果表很短,宏更容易读,但如果文件很长,特殊文件更有意义。
最后一个选项是使用完全不同格式的表并生成代码,但这需要编写一些特殊的脚本来构建它,而这没有。
预处理器(在任何之前运行),当它偶然发现include
时,几乎是从字面上复制该头指令的内容并将其粘贴到#include
指令的位置。
像你描述的那样使用它的好处很少,主要的是你不必重复代码。
然而,在9999/10000的情况下,这绝对不值得这么麻烦。如果你在头文件的某个地方有一个错别字,你会在每个使用它的文件中得到奇怪的错误,并且在你真正打开文件并读取它之前根本不清楚它在做什么。
尽量避免。我想不出有什么情况是绝对必要的;在大多数情况下,通过继承或组合可以实现相同的效果,而不会产生任何副作用。
在像Ruby这样的语言中,这个概念被称为Mixin。因为c++中有多重继承,所以这里不需要。
我发现的一种用法是,如果您想在类定义中自动生成大量行,那么像这样包含自动生成的文件可能会很有帮助。
这些答案都很老了,但我找到了一个上面没有列出的原因。我正在编写需要访问私有成员的自动化测试,因此在许多类中使用友谊声明。由于友谊不是继承的,因此我必须在与之交互的每个类中显式声明任何新测试类的友谊。
如果有一个或多个文件按照"test_friends.h"列出我的测试类,这就容易多了:
friend class testOneFeature;
friend class testAnotherFeature;
等,在测试的类中,我可以简单地将该文件包含在声明中。
class MyClass
{
#include "test_friends.h"
public:
//etc
};
只是无意中发现了这一点,这对gtest fixture非常有用,因为您需要将每个测试fixture声明为FRIEND_TEST(),以便能够访问私有/受保护的成员。
- 使用mongocxx驱动程序时包含头文件问题
- 如何为包含头文件的目标编写生成文件?
- 如何在 CMakeLists.txt Qt Creator 中包含头文件?
- 当包含头文件的文件不在根项目文件夹中时,如何包含它
- 在生成文件先决条件中包含头文件的原因
- My Project的属性配置正确,但Visual Studio仍然无法打开包含头文件
- 在 PostgreSQL C 扩展中包含头文件
- 是否可以在C++中以间接方式包含头文件
- 是否需要包含头文件?
- 我收到未声明的标识符错误,但我已包含头文件?
- 为什么我们需要构建一个提升库,仅仅包含头文件还不够吗,因为提升是模板
- C++:当顺序真正重要时,如何保证在项目中包含头文件的顺序
- 如何在C++中包含头文件时错误地重载
- 我在C++中无效使用不完整的类型类错误,如何正确包含头文件?
- 虚幻引擎4.16,C++包含头文件
- C++多次包含头文件
- 令牌之前的预期类名 '{' - 包含头文件和 CPP 文件
- 在.cpp中包含头文件会导致令人讨厌的错误
- 如何列出用于在Qt项目中包含头文件的所有路径
- 尽管包含头文件,但仍找不到嵌套命名空间