之前一直用C#开发框架,最近在liunx上,改用c++开发程序应用框架。感觉c#的get set属性功能颇为好用。
在c++中每次都得写一长串,不开心了。发现有个老外写了一篇 c++ Propertiest(来源:http://www.codeproject.com/Articles/118921/C-Properties ),当然国内有热心同仁翻译了。(http://blog.csdn.net/problc/article/details/5954470)。
如果您只看原文或译文就完全明白原作者的意思了,又或者完全没兴趣了解原作者的意思,那就请别看下去了,会浪费您的时间。
如果你只是想拿来主义地使用一下,那就直接copy粘帖即可。不过我写本文的目的是再次给各位有志于成为高端开发软员的同行们,分享一下学习经验,所以打算在翻译好的文档的基础上,进一步滴解释一下c++的一些高端用法,在这里主要是宏(也没那么高端,不是么?)。
原文提到了c#的getter stter做的多么多么好,软件工程性多么多么高。
private int _x;
public int x
{
get
{
return _x;
}
set
{
_x = value;
}
}
someObject.x = 50;
你看,轻轻松松就能得到一个可读可写的的属性。
当然,c语言也能做的一样好,就是你得废点劲。
我们用宏来实现,
#define PROPERTY(t,n) __declspec( property \
( put = property__set_##n, get = property__get_##n ) ) t n;\
typedef t property__tmp_type_##n
#define READONLY_PROPERTY(t,n) __declspec( property (get = property__get_##n) ) t n;\
typedef t property__tmp_type_##n
#define WRITEONLY_PROPERTY(t,n) __declspec( property (put = property__set_##n) ) t n;\
typedef t property__tmp_type_##n
#define GET(n) property__tmp_type_##n property__get_##n()
#define SET(n) void property__set_##n(const property__tmp_type_##n& value)
宏本身很简单,就是代码替换,在编译器正式编译代码之前,它会先将代码中的字符替换成预先定义的宏(如果你有定义过的话)
例如
#define Pi 3.1415
#include <iostream>
using namespace std;
main()
{
float Pi;
round = Pi * 2; //这里在编译成程序之前,会先替换成round = 3.1415 * 2;
cout << Pi << endl;
}
宏很简单把,但是在这里还是有点小技巧,大家注意到第二行,put = proterty_set_##n
宏的符号##
这里解释一下 # 以及 ## 。
在宏中如果出现 # + 形参 那么在实际替换中就是将实际参数加上了引号,如果实际参数中有引号或者 \,那么会替换成 \" 及 \\这是为了保证替换出的是一个合法字符串。
例如:
#define myprint(result) printf(#result "=%\n" , result)
<pre name="code" class="cpp">#include <iostream>
using namespace std;</pre>main(){ int x = 1; int y = 2; myprint(x+y); // print("x+y = %\n", x+y);}
与#类似的, ##也是用于连接实际参数的功能,不过它就没有额外增加符号之类的功能了,它是将参数去掉前后的空格,直接连到字符串上,
例如本文例子的第二行在执行宏替换后就变成了, put = propert_set_实际参数,这个做的目的应该是为了避免出现重名的问题。
接下来,在宏里面还有一段__declspec,这个是微软的力作,随便搜一下百度就能知道__declspec(dllexport) __declspec(dllimport)是用来标定函数或者类或者变量是被导出或者导入的。在一个dll中用declspec导出,则在另一个程序中jiu可以用declspec来导入,使用declspec可以比传统的def文件更简单点。
另外declspec有很多参数,例如 align (指定数据类型对其格式),在这里我们看到的是propert参数
在vc6里面,该参数的含义是:该属性可用于类或结构定义中的非静态“虚数据成员”。实际上就是做了一个映射,把你的方法映射成属性,以供访问。get和put就是属性访问的权限,一个是读的权限,一个是写的权限。当编译器看到被property修饰的数据成员出现在成员选择符("." 或 "->")的右边的时候,它将把该操作转换成get或put方法。该修饰符也可用于类或结构定义中的空数组。
其他更多参数请看(http://wanglei87814.blog.163.com/blog/static/69042982201071010505126/)
所以在vc编译环境下,我们实现c#属性的代码主要就是利用了declspec这个宏指令。
当然,这种用法有其局限性,这就很复杂了,这里有一篇英文博客 (http://blog.aaronballman.com/2011/11/an-almost-useful-language-extension/),要想看懂这篇文章,你需要了解汇编语言(还有英文,不过你也可以安装英文电子词典,不过我还是觉得学好英文是学好计算机的前提)