我偶然发现了以下代码,并且发现了解嵌套宏并在其中输入类型非常复杂。
当我尝试编译代码时,我遇到了错误
需要解释下面的代码。
为什么BEGIN_STATE_MAP和END_STATE_MAP在Motor.h中设置为标签,这对我来说真的很新
提前致谢
Motor.h
// the Motor state machine class
class Motor : public StateMachine
{
public:
Motor() : StateMachine(ST_MAX_STATES) {}
// external events taken by this state machine
void Halt();
void SetSpeed(MotorData*);
private:
// state machine state functions
void ST_Idle();
void ST_Stop();
void ST_Start(MotorData*);
void ST_ChangeSpeed(MotorData*);
// state map to define state function order
BEGIN_STATE_MAP
STATE_MAP_ENTRY(ST_Idle)
STATE_MAP_ENTRY(ST_Stop)
STATE_MAP_ENTRY(ST_Start)
STATE_MAP_ENTRY(ST_ChangeSpeed)
END_STATE_MAP
// state enumeration order must match the order of state
// method entries in the state map
enum E_States {
ST_IDLE = 0,
ST_STOP,
ST_START,
ST_CHANGE_SPEED,
ST_MAX_STATES
};
};
#endif //MOTOR_H
什么是BEGIN_STATE_MAP和END_STATE_MAP,这个定义我发现我真的很新, BEGIN_STATE_MAP和END_STATE_MAP是以下头文件中定义的宏。
StateMachine.h
#ifndef STATE_MACHINE_H
#define STATE_MACHINE_H
#include <stdio.h>
#include "EventData.h"
struct StateStruct;
// base class for state machines
class StateMachine
{
public:
StateMachine(int maxStates);
virtual ~StateMachine() {}
protected:
enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN };
unsigned char currentState;
void ExternalEvent(unsigned char, EventData* = NULL);
void InternalEvent(unsigned char, EventData* = NULL);
virtual const StateStruct* GetStateMap() = 0;
private:
const int _maxStates;
bool _eventGenerated;
EventData* _pEventData;
void StateEngine(void);
};
typedef void (StateMachine::*StateFunc)(EventData *);
struct StateStruct
{
StateFunc pStateFunc;
};
#define BEGIN_STATE_MAP \
public:\
const StateStruct* GetStateMap() {\
static const StateStruct StateMap[] = {
#define STATE_MAP_ENTRY(entry)\
{ reinterpret_cast<StateFunc>(entry) },
#define END_STATE_MAP \
{ reinterpret_cast<StateFunc>(NULL) }\
}; \
return &StateMap[0]; }
#define BEGIN_TRANSITION_MAP \
static const unsigned char TRANSITIONS[] = {\
#define TRANSITION_MAP_ENTRY(entry)\
entry,
#define END_TRANSITION_MAP(data) \
0 };\
ExternalEvent(TRANSITIONS[currentState], data);
#endif
EventData.h
#ifndef EVENT_DATA_H
#define EVENT_DATA_H
class EventData
{
public:
virtual ~EventData() {};
};
#endif //EVENT_DATA_H
虽然我试图编译上面的代码.Below是遇到的错误
错误
-------------- Build: Debug in StateMachine (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -Wall -fexceptions -g -pedantic -Wzero-as-null-pointer-constant -std=c++0x -Wextra -Wall -c C:\Users\xprk569\StateMachine\main.cpp -o obj\Debug\main.o
In file included from C:\Users\xprk569\StateMachine\main.cpp:2:0:
C:\Users\xprk569\StateMachine\Motor.h: In member function 'virtual const StateStruct* Motor::GetStateMap()':
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:29:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_Idle)
^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:30:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_Stop)
^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:31:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_Start)
^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:32:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_ChangeSpeed)
^
C:\Users\xprk569\StateMachine\StateMachine.h:43:39: error: invalid cast from type 'int' to type 'StateFunc {aka void (StateMachine::*)(EventData*)}'
{ reinterpret_cast<StateFunc>(NULL) }\
^
C:\Users\xprk569\StateMachine\Motor.h:33:5: note: in expansion of macro 'END_STATE_MAP'
END_STATE_MAP
^
Process terminated with status 1 (0 minute(s), 0 second(s))
5 error(s), 0 warning(s) (0 minute(s), 0 second(s))
有些人可以解释为什么在Motor.h中以这样的方式编写宏, 为什么在StateMachine.h和 为什么会抛出错误?
先谢谢
答案 0 :(得分:1)
看起来这段代码依赖于一些非标准的编译器扩展/错误。
要编译它(不知道它是否真的有效)你需要用完全限定的成员函数指针替换函数名:
e.g。
BEGIN_STATE_MAP
STATE_MAP_ENTRY(&Motor::ST_Idle)
STATE_MAP_ENTRY(&Motor::ST_Stop)
STATE_MAP_ENTRY(&Motor::ST_Start)
STATE_MAP_ENTRY(&Motor::ST_ChangeSpeed)
END_STATE_MAP
在那之后,你需要找到克服不合规演员阵容的方法:
/tmp/gcc-explorer-compiler116314-75-1uiyu0/example.cpp: In member function 'virtual const StateStruct* Motor::GetStateMap()':
44 : error: invalid cast from type 'long int' to type 'StateFunc {aka void (StateMachine::*)(EventData*)}'
{ reinterpret_cast<StateFunc>(NULL) }\
^
83 : note: in expansion of macro 'END_STATE_MAP'
此演员表是完全非法的。如果我是你,我会将代码丢弃并重写 - 或者使用经过验证的状态机框架,如boost meta state machine或boost statechart。
答案 1 :(得分:0)
因此,您可以快速了解为什么Macros在可读的C ++中是无效的。如果出现错误,则必须将宏扩展为识别错误的位置,在大多数IDE中也无法调试它们。
无论如何说,让我们进行扩展,他们的所有相同的错误,所以我们只看第一个:
C:\ Users \ xprk569 \ StateMachine \ Motor.h:29:9:注意:扩展宏
STATE_MAP_ENTRY
时STATE_MAP_ENTRY(ST_Idle)
C:\ Users \ xprk569 \ StateMachine \ StateMachine.h:40:40:错误:无效使用成员(你忘记了&
吗?)
{ reinterpret_cast<StateFunc>(entry) },
所以这是抱怨第29行:STATE_MAP_ENTRY(ST_Idle)
所以让我们扩展一下:
{ reinterpret_cast<StateFunc>(entry) },
显然,在BEGIN_STATE_MAP
和END_STATE_MAP
的范围之外,这是一个错误的语法,因此在调试许多宏时,您还必须查看范围宏...有时它们可能会不幸的是,没有明确的命名或描述,但让我们完成定义我们首先得到错误的行。我们试图加入的StateFunc
是什么?
typedef void (StateMachine::*StateFunc)(EventData *);
它是指向成员函数的指针,该函数返回void
并接受EventData *
。警钟应该响起。你不能投! ST_Idle
的格式为: void (StateMachine::*)()
,因此您无法转换为void (StateMachine::*StateFunc)(EventData *)
。对于传递给宏的所有函数,这都是同样的问题,它们都没有返回void
并取EventData*
,因此即使您修复了语法,这些reinterpret_cast
也将始终返回指向一个无法调用的方法的指针,这意味着整个宏块在最好的情况下是无意义的,在最坏的情况下是有毒的。在当前状态下,您也可以不使用这些宏,或者只需要定义方法:
BEGIN_STATE_MAP
END_STATE_MAP
但是,如果您要将方法声明更改为更像:
void ST_Idle(EventData*);
然后您需要使用以下语法:
STATE_MAP_ENTRY(&Motor::ST_Idle)
如果您没有使用方法指针,那么它们非常复杂。我在这里输入了一个简单的示例:http://ideone.com/nL0HnQ随意对问题发表评论。
修改强>
要在此扩展宏,我们将获得:
public: // BEGIN_STATE_MAP
const StateStruct* GetStateMap() { // BEGIN_STATE_MAP
static const StateStruct StateMap[] = { // BEGIN_STATE_MAP
{ reinterpret_cast<StateFunc>(ST_Idle) } // STATE_MAP_ENTRY(ST_Idle)
{ reinterpret_cast<StateFunc>(ST_Stop) } // STATE_MAP_ENTRY(ST_Stop)
{ reinterpret_cast<StateFunc>(ST_Start) } // STATE_MAP_ENTRY(ST_Start)
{ reinterpret_cast<StateFunc>(ST_ChangeSpeed) } // STATE_MAP_ENTRY(ST_ChangeSpeed)
{ reinterpret_cast<StateFunc>(NULL) } // END_STATE_MAP
}; // END_STATE_MAP
return &StateMap[0]; } // END_STATE_MAP
所以这组宏将会:
public
GetStateMap
StateMap
静态声明为GetStateMap
,它将是StateStruct
s GetStateMap
方法StateMap
的第一次调用中,将初始化为包含ST_Idle
,ST_Stop
,ST_Start
,ST_ChangeSpeed
的方法指针}和NULL
reinterpret_cast
到StateFunc
s GetStateMap
以返回StateMap
数组