向类添加动态方法:将宏函数用于头文件

时间:2017-08-04 14:36:54

标签: c++ macros

尽量避免写重复代码;我使用宏来将方法分成一个类。 我想在头文件中定义一个宏函数,如:

cracker.h

#include<message.h>
class Cracker {
    #define DECLARE_MSG(MSG_NAME, MSG_TYPE,ALREADY_DEFINED)      \
    { \                                                                                

        if(!ALREADY_DEFINED)                                                           
        {                                                                                \
            virtual bool cbProcessMsg_##MSG_NAME (API::MSG_NAME##Msg const & msg);                         \
        }\
    #include "message.h"
    #undef DECLARE_MSG
    };

message.h

DECLARE_MSG(AddOrder , 'A', false);
DECLARE_MSG(DeleteOrder , 'B', true);
DECLARE_MSG(ReplaceOrder , 'C', false);
...

但是这段代码注意到编译,因为我无权在函数外添加if语句。

还有其他选择吗?

2 个答案:

答案 0 :(得分:2)

有几个值得强调的项目:

1。 宏不知道范围;你可以删除它的唯一方法就是取消定义它。

2。 宏按原样粘贴到代码中;然后编译。宏本身不是一个函数,它是一个代码生成工具。这意味着即使'ALREADY_DEFINED'为真,您也会得到另一个定义。

3。 你要做的是在类定义之外的类中添加一个函数。你不能这样做。如初。

4。 头部防护装置将为您节省大中型项目的痛苦;你应该早点进入使用它们的习惯。

虽然不完全相同,但您想要做的是查看工厂模式。

答案 1 :(得分:0)

如果您(可以)使用boost-library,请使用BOOST_PP_IIF

#define DECLARE_MSG(MSG_NAME, MSG_TYPE,ALREADY_DEFINED)    \                                                                                
    BOOST_PP_IIF(ALREADY_DEFINED,, \                                                                                                                     
        virtual bool cbProcessMsg_##MSG_NAME (API::MSG_NAME##Msg const & msg);                         \
    )

您应该使用01代替falsetrue

但是如果你不这样做,你可以通过将名称和数字连接到另一个宏来“分支”定义:

// two definitions for PP_CONCAT to expand macros, etc...
#define PP__CONCAT(a, b) a ## b
#define PP_CONCAT(a, b) PP__CONCAT(a, b)

// to expand your macro you should pass it through another macro
#define PP_EXPAND(...) __VA_ARGS__

#define DECLARE_MESSAGE_0(MSG_NAME, MSG_TYPE) /** the def when ALREADY_DEFINED = 0 */
#define DECLARE_MESSAGE_1(MSG_NAME, MSG_TYPE) /** the other branch */

#define DECLARE_MESSAGE(MSG_NAME, MSG_TYPE, ALREADY_DEFINED) \
    PP_EXPAND(PP_CONCAT(DECLARE_MESSAGE_, ALREADY_DEFINED)(MSG_NAME, MSG_TYPE))

如果您在理解预处理器时遇到问题,则应使用选项-E /检查输出,并使用命令cpp运行代码(代表 c - p re p rogressor和 c p lus p lus ( - &GT; c++))

然而,使用模板和继承可能还有另一种方法可以做同样的事情......