c++ 宏定义 ## 的使用

一年半前,见过宏定义##的使用,实现类似反射机制,通过字符串创建类对象的代码,感觉很神奇。

两个月前,利用##的语法,实现一个小功能,通过机组字符串排列组合,调用一个万行代码,计算功能类的函数接口。

三四天前,简单概要的把代码提纯,记录下来,以备后用。代码量不多,但每次写都好费劲,至少写了5遍了,仍然费劲。

main.cpp

 1 #include <iostream>
 2 #include "register.h"
 3 #include "registerfun.h"
 4
 5 using namespace std;
 6
 7
 8 int main()
 9 {
10     //1.使用##创建对象,创建同类,不同对象
11     cout << "1." <<endl;
12     Init();
13     Create("CObjectA");
14     Create("CObjectA");
15     Create("CObjectB");
16
17     //2.使用##调用对象函数
18     cout << "2." <<endl;
19     InitFun();
20     CallFun("Welcome1");
21     CallFun("Welcome2");
22
23     return 0;
24 }

register.h

 1 #ifndef _REGISTER_H_
 2 #define _REGISTER_H_
 3
 4 #include <iostream>
 5 #include <string>
 6
 7 #include "instance.h"
 8
 9 extern"C" bool Init(void);
10 extern"C" bool Clear();
11 extern"C" IObj* Create(const string& name);
12
13 #endif

register.cpp

#include "register.h"

#include <iostream>
#include <string>
#include <map>

using namespace std;

//宏定义的一种用法,可实现类似反射的 c++ 功能。宏定义的神奇,减少代码量,类似泛型的感觉
#define IMPLEMENT_CREATE_OBJ(classname)    static IObj* _create_obj##classname()    {        return new classname();    }
#define CREATE_OBJ_FUN(classname) _create_obj##classname

//函数指针
typedef IObj* (*FCreateObj)(void);
//函数指针的map类型
typedef map<string, FCreateObj> StrCreateFunMap;

//通过宏定义实现各种函数指针
IMPLEMENT_CREATE_OBJ(CObjectA)
IMPLEMENT_CREATE_OBJ(CObjectB)

//定义一个函数指针的map
StrCreateFunMap g_strCreateFunMap;

bool Init(void)
{
    g_strCreateFunMap["CObjectA"] = CREATE_OBJ_FUN(CObjectA);
    g_strCreateFunMap["CObjectB"] = CREATE_OBJ_FUN(CObjectB);
    return true;
}

bool Clear()
{
    return true;
}

IObj* Create(const string& name)
{
    return (*(g_strCreateFunMap[name]))();
}

registerfun.h

 1 #ifndef _REGISTER_FUN_H_
 2 #define _REGISTER_FUN_H_
 3
 4 #include <iostream>
 5 #include <string>
 6 #include <map>
 7
 8 #include "instance.h"
 9
10 using namespace std;
11
12 extern"C" bool InitFun(void);
13 extern"C" bool ClearFun(void);
14 extern"C" bool CallFun(const string& name);
15
16 #endif

registerfun.cpp

#include "registerfun.h"

#include <iostream>
#include <string>
#include <map>

using namespace std;

#define IMPLEMENT_CALL_FUN(funname)    static void _call_instance##funname()    {        CInstance* p = CInstance::GetInstance();        p->funname();    }
#define CALL_FUN(funname) _call_instance##funname

typedef void(*FCallFun)(void);
typedef map<string, FCallFun> StrCallFunMap;

IMPLEMENT_CALL_FUN(Welcome1)
IMPLEMENT_CALL_FUN(Welcome2)

StrCallFunMap g_strCallFunMap;

bool InitFun()
{
    g_strCallFunMap["Welcome1"] = CALL_FUN(Welcome1);
    g_strCallFunMap["Welcome2"] = CALL_FUN(Welcome2);
    return true;
}

bool ClearFun()
{
    return true;
}

bool CallFun(const string& name)
{
    (*(g_strCallFunMap[name]))();
    return true;
}

instance.h

 1 #ifndef _INSTANCE_H_
 2 #define _INSTANCE_H_
 3
 4 #include <iostream>
 5 #include <string>
 6
 7 using namespace std;
 8
 9 class IObj
10 {
11 public:
12     virtual void Welcome()=0;
13 };
14 class CObjectA : public IObj
15 {
16 public:
17     CObjectA();
18     virtual ~CObjectA();
19     void Welcome();
20 };
21 class CObjectB : public IObj
22 {
23 public:
24     CObjectB();
25     virtual ~CObjectB();
26     void Welcome();
27 };
28 class CInstance
29 {
30 private:
31     CInstance();
32     virtual ~CInstance();
33 public:
34     static CInstance* GetInstance();
35     void Welcome1();
36     void Welcome2();
37 private:
38     static CInstance* m_pInstance;
39 };
40
41 #endif

instance.cpp

#include "instance.h"

//
CObjectA::CObjectA()
{
    Welcome();
}
CObjectA::~CObjectA()
{
}
void CObjectA::Welcome()
{
    cout << "CObjectA welcome " << this <<endl;
}

//
CObjectB::CObjectB()
{
    Welcome();
}
CObjectB::~CObjectB()
{
}
void CObjectB::Welcome()
{
    cout << "CObjetcB Welcome " << this <<endl;
}

//静态私有类成员变量赋值
CInstance* CInstance::m_pInstance = NULL;
CInstance::CInstance()
{
}
CInstance::~CInstance()
{
}
CInstance* CInstance::GetInstance()
{
    if (m_pInstance == NULL) {
        m_pInstance = new CInstance();
    }
    return m_pInstance;
}
void CInstance::Welcome1()
{
    cout << "CInstance Welcome1"<<endl;
}
void CInstance::Welcome2()
{
    cout << "CInstance Welcome2"<<endl;
}
时间: 2024-08-04 01:03:26

c++ 宏定义 ## 的使用的相关文章

宏定义中的#,##,...,do{}while(0),__VA_ARGS__

宏定义中的#,## 1.在一个预处理器宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组 #define syslog(a) fprintf(stderr,"Warning: " #a"\n"); 2.简单的说,"## "是一种分隔连接方式,它的作用是先分隔,然后进行强制连接 举列 -- 试比较下述几个宏定义的区别 #define A1(name, type)  type name_##type##_type 或 #define A

笔记3:预处理器-(2)宏定义

#define指令称为宏定义指令,通常用#define指令来定义一个宏用来代表其他东西的一个名字(如常量表达式等).通常来说预处理器会通过将宏的名字和它的定义存储在一起来响应#define指令.当这个宏在后面的程序中使用到时,预处理器会"扩展"宏,将宏替换为其定义值. 简单的宏 简单的宏的定义格式: #define 标识符 替换列表 如: #define DTE_LEN 80 #define TRUE 1 #define FALSE 0 #define PI 3.1415926 #de

宏定义中使用do{}while(0)的好处 (转载)

宏定义中使用do{}while(0)的好处   #define MACRO_NAME(para) do{macro content}while(0) 的格式,总结了以下几个原因: 1,空的宏定义避免warning: #define foo() do{}while(0) 2,存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现. 3,如果出现在判断语句过后的宏,这样可以保证作为一个整体来是实现: #define foo(x) /action1(); /action2(); 在以下情况

Android.mk宏定义demo【转】

本文转载自:http://blog.csdn.net/u010164190/article/details/72783963 1.Android.mk  LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := binder_demo_showLOCAL_MODULE_TAGS := optionalLOCAL_SRC_FILES := test.cpp TARGET_BUILD_VARINT := userdebug #宏

c++编译时打印宏定义

#pragma message("this is message") #pragma message只能打印字符串,如果想打印任何宏定义可使用: #define PRINT_MACRO_HELPER(x) #x #define PRINT_MACRO(x) #x"="PRINT_MACRO_HELPER(x) #pragma message(PRINT_MACRO(var)) 如:#define __cplusplus 199911L #pragma message

typedef与define宏定义用于声明新的类型之间的区别

摘自<c专家编程> typedef可以看成一种彻底的封装类型,在typedef声明类型之后不能再往里面增加其他的内容. 例子: #define peach int unsigned peach i; //没问题 typedef int banana; unsigned banana i; //错误,不能增加unsigned #define宏定义只是用于简单的替换 #define int_ptr int * int_ptr chalk, cheese; int * chalk, cheese;

c 预处理的宏定义

概念 以“#”号开头的都是预处理命令 例如 #include <stdio.h>宏定义 宏定义无参数的宏名后不带参数# 表示这是一条预处理命令, define 为宏定义命令.“标识符”为所定义的宏名.“字符串”可以是常数,表达式.格式串等 举例: #define PI 3.1415926 作用: 就是用指定标识符PI来代替数3.1415926 对源程序作编译时, 将先由预处理程序进行宏代换, 即用3.1415926表达式去置换所有的宏名PI, 然后编译 #include <stdio.h

C语言学习——宏定义

1.简单的宏定义 #define <宏名> <字符串> 例:#define LEN 0.5 2.带参数的宏定义 #define <宏名> (<参数表>) <宏体>例:#define Fun(para) para*2 3.实例分析 1 #define VALUE 2+2 2 void main() 3 { 4 int n=VALUE*VALUE; 5 printf("%d",n); 6 } 这段代码的输出是多少呢?16?也许会让

宏定义与内联函数

1.宏定义的规则和使用解析(1)宏定义的解析规则就是:在预处理阶段由预处理器进行替换,这个替换是原封不动的替换.(2)宏定义替换会递归进行,直到替换出来的值本身不再是一个宏为止.(3)一个正确的宏定义式子本身分为3部分:第一部分是#dedine ,第二部分是宏名 ,剩下的所有为第三部分.(4)宏可以带参数,称为带参宏.带参宏的使用和带参函数非常像,但是使用上有一些差异.在定义带参宏时,每一个参数在宏体中引用时都必须加括号,最后整体再加括号,括号缺一不可. 宏定义示例1:MAX宏,求2个数中较大的

【转】C语言中DEFINE简介及多行宏定义

要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义.那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍. 我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义: #define MAX( a, b) ( (a) > (b) (a) : (b) ) 其次,把它用函数来实现: int max( int a, int b)