我一直在尝试编写自己的状态机,其中每个状态都是从状态基类派生的单独类。
无论我包含我的state_t类文件(#include“state_t.h”),我都希望包含所有派生的状态类标题,所以每次我需要使用时,我都不必单独包含它们状态机或创建新状态。
因为在state_t.h结束之前没有定义“state_t”我只能在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
这是我的main.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();
}
注意:代码一切正常,这真的是一个“正确性”的问题。
答案 0 :(得分:5)
根据您的具体示例:
这是一个坏主意。您在基本和派生类型之间引入了一个非常紧密的耦合,方向错误。基类应该对其派生类型一无所知。这是允许它成为有效基类的事情之一。在当前的方案中,每次编写派生类型时,都必须触及基类的标题,强制编译时依赖于基类的所有客户端代码。除此之外,您还有一个循环包含依赖项。
一般:
在非病理情况下,这取决于具体情况。关于头文件,人们可能会争辩说知道文件需要哪些头是好的,在这种情况下,它们在顶部是有意义的。但是,如果包含被认为是只会分散注意力的实施细节,则可以将它们放在底部。根据我的经验,这特别适用于模板代码的实现,以及匿名命名空间中的辅助类和内联函数的实现。
答案 1 :(得分:4)
就个人而言,我更倾向于将所有包含在顶部。您可以在其他标题中使用前向声明来解决定义顺序问题。
但这只是一种风格的东西 - “正确”明智,没有理由你不能这样做。您可以在任何您喜欢的地方有效地包含任何内容,这可能会在以后引起混淆!
答案 2 :(得分:1)
根据我的说法,这只是一个约定,因为每个人都这样做,标准开发人员如果需要添加一些文件,将不会查看文件的末尾,这将是一些包括在顶部,一些包括在底部。
答案 3 :(得分:1)
我更喜欢把我的包括在顶部,否则可能有点困惑。我的建议是不要在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