包含在头文件的末尾,是否安全/良好做法

include at the end of a header file, is it safe/good practise?

本文关键字:安全 是否 文件 包含      更新时间:2023-10-16

我一直在尝试编写自己的状态机,其中每个状态都是从状态基类派生的单独类。

无论我在哪里包含我的state_t类文件(#include"state_t.h"),我都希望包含所有派生的状态类标头,这样我就不必在每次需要使用状态机或创建新状态时单独包含它们。

由于"state_t"直到 state_t.h 末尾才定义,因此我只能在文件 state_t.h 的末尾包含我的状态文件。我以前从未编写过这样做的代码,这似乎有点奇怪!我可以添加一个顶级的"statemachine.h",将所有文件收集在一起,但这似乎是一种浪费。

我的问题是:这样做是否正确/安全/可以? 有什么缺点/问题吗?

注意:目前我的代码都是测试代码,它是用Qt编写的,但它应该是一个直接的C ++问题。

这是我的基类 (state_t.h) - 请注意最后的 #include

#ifndef STATE_T_H
#define STATE_T_H
#include <QByteArray>
#include <QDebug>
class state_t
{
public:
    state_t(QByteArray stateName);
    virtual ~state_t();
    virtual state_t * processState(int input) = 0;
    QByteArray getState();
    QByteArray name;
};
#include "teststate1.h"
#include "teststate2.h"
#endif // STATE_T_H

下面是一个状态派生类(teststate1.h):

#ifndef TESTSTATE1_H
#define TESTSTATE1_H
#include "state_t.h"
class testState1 : public state_t
{
public:
    testState1();
    state_t *processState(int input);
};
#endif // TESTSTATE1_H

这是我的主要.cpp:

#include <QCoreApplication>
#include <QDebug>
#include "state_t.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    state_t *myState = new testState1();
    myState = myState->processState(1);
    myState = myState->processState(2);
    myState = myState->processState(3);
    myState = myState->processState(1);
    return a.exec();
}

注意:代码都运行良好,这实际上是一个"正确性"的问题。

给定您的特定示例

这是一个坏主意。您在错误的方向上引入了基类型和派生类型之间的非常紧密的耦合。基类应该不知道其派生类型。这是使它成为一个有效的基类的原因之一。在当前的方案中,每次编写派生类型时,都必须触摸基的标头,从而强制编译时依赖于基的所有客户端代码。除此之外,您还有一个循环包含依赖项。

一般来说

在非病理性病例中,这取决于情况。关于头文件,有人可能会争辩说,最好知道文件需要哪些头文件,在这种情况下,将它们放在顶部是有意义的。但是,如果包含被认为是只会分散注意力的实现细节,则可以将它们放在底部。根据我的经验,这特别适用于模板代码的实现,以及匿名命名空间中帮助程序类和内联函数的实现。

就个人而言,我宁愿将所有包含的内容放在顶部。 您可以在其他标头中使用前向声明来解决定义顺序问题。

但这只是一种风格——"正确性"明智,没有理由你不能这样做。 您可以有效地在任何地方包含任何您喜欢的内容,只是以后可能会引起混淆!

据我说,这只是一个约定,因为每个人都这样做,如果标准开发人员需要添加一些,他不会查看文件的末尾,这将是一团糟,一些包含在顶部,一些在底部。

我更喜欢将我的包含放在顶部,否则可能会有点混乱。我对你的建议是不要在 test_t.h 中包含 teststate1.h 和 teststate2.h,而是创建 state_all.h

#include "state_t.h"
#include "teststate1.h"
#include "teststate2.h"

并在您需要的地方包括 state_all.h 而不是 state_t.h