1

首先,我设法在单个头文件中实现了一个状态机。我知道我需要一些前向声明,并且我必须从外到内定义状态。我真正不明白的是:我将如何处理多个文件?

我的方法:

  • 每个状态一个标题
  • 一个包含所有可能状态的标头,前向声明
  • 每个声明状态的标头都包含声明其上下文的标头

然后它看起来像这样:

// forward.h
struct Machine;
struct StA;
struct StB;

// machine.h
#include "forward.h"
struct Machine : sc::state_machine< Machine, StA > {};

// a.h
#include "forward.h" // for StB
#include "machine.h"
struct StA : sc::simple_state< StA, Machine, StB > {};

// b.h
#include "forward.h"
#include "a.h"
struct StB : sc::simple_state< StB, StA > {};

现在,如何将整个内容包含在程序中仍然是开放的。我的想法是有一个标题,其中包括从外部到内部所有州的标题。

// the_machine.h
#include "forward.h"
#include "machine.h"
#include "a.h"
#include "b.h"

// use this header now where you need the state machine

但是,我不知道一般的想法是否可以,即使可以,我也无法编译它(嗯,不完全是这个,而是我按照这个设计原则建造的机器)。一旦你意识到上下文需要完整,状态需要提前声明等等,将所有内容放在一个文件中就很容易了,但是由于复杂性和维护原因而拆分让我很紧张......Incomplete type 'StXY' used in nested name specifier等等。

4

1 回答 1

2

Incomplete type如果您弄乱了包含标题的顺序,则通常会出现该错误。

  • 您是否在头文件中使用了正确的包含保护?
  • 当你有循环包含时,有时前向声明会搞砸。
  • 有时,人们会复制一个标题来制作一个类似的标题(egah 和 bh)而忘记更改包含保护。这可能很难追踪。

试试下面的方法:创建一个空的 .cpp,它只包含the_machine.h并且只预编译它。对于编写包含预处理翻译单元的文件(即一个包含编译器可以看到的所有代码的文件)的不同编译器,有命令行标志。检查该文件以查看所有内容是否按照您认为的顺序进行。大多数预处理器生成#line控制命令,告诉编译器(和您)您正在查看的标头/源代码的哪一行。

编辑:

如果您只想使用#includemachine.h,则必须在机器定义之后包含状态定义。乍一看这可能看起来很奇怪,但如果您想拆分依赖部分,这就是它与模板一起工作的一般方式。许多人对后面包含的部分使用不同的文件后缀,因为它们本身并不是真正的标题,即您不能单独包含它们。例子:

//Something.h
template <class T>
struct Something
{
   void meow(T const& t);
   int wuff(T const& t, int b);
};

#include "Something.impl" //or .ipp, or other endings...

//Something.impl
template <class T>
void Something<T>::meow(T const& t)
{ /* implement... */ }

template <class T>
int Something<T>::wuff(T const& t, int b)
{ /* implement... */ }

您的 machine.h 看起来很相似 - 定义机器并在其后包含状态的实现。我不会命名州的实施文件X.h,因为它们不是一个可以单独包含和使用的单个标头。

于 2013-01-18T09:20:08.810 回答