文档章节

[C/C++]属性的秘密——C++仿C#的属性实作

梁欢
 梁欢
发布于 2013/11/10 18:07
字数 707
阅读 1.2K
收藏 10
一直以来,我都想为C++引入C#里面定义的属性(Property),我尝试了几次:
读过上面三篇文章后就会发现,一直以来,我对属性的认识都是错误的,我的关注点全部放在了属性值的变化怎么被通知出去,而这在C#的属性定义中根本就是不被关注的。我们先看一下C#是怎么实现属性的。
首先我们写一个C#的普通类:
class A
{
    public double pp { get; set; }
    public double pv { get; protected set; }
    public double vp { protected get; set; }
}
然后再看反编译之后的IL代码:

可以看到一个属性被分解成三块:域(Field)、getter和setter、存取器(Accessor)。
Field是C#类的成员变量被定义的地方,对应C++也是类的成员变量定义(可访问性为:private);
getter和setter是C#类的成员函数,对应C++也是类的成员函数(可访问性为:private、protect或者public);
Accessor才是C#真正实现属性语法的地方(如下图所示),对应C++可以使用operator运算符实现。

如果仅仅考虑前两条,用C++很容易的就能使用宏展开模仿出来:
#define AutoProperty(ValueType, GetAccessor, SetAccessor, Variable)	private: ValueType Variable;\
GetAccessor: ValueType get##Variable() { return Variable; }\
SetAccessor: void set##Variable(ValueType newValue) { Variable = newValue; }
AutoProperty分为四个部分:ValueType是变量的类型;GetAccessor、 SetAccessor分别是getter和setter的可访问性;Variable是变量的名称。AutoProperty使用起来非常简单:
// 任务是否可以运行,只读属性
AutoProperty(bool, public, protected, CanRun);
但是当外部或子类使用如上定义的CanRun属性的时候,却只能通过getCanRun()和setCanRun()这一对成员函数,而不像C#那样简单。
下面我们考虑用C++模拟出C#的 Accessor实现的功能。
#include <functional>
using namespace std;

template<typename ValueType>
class Property
{
protected:
	typedef function<ValueType()> GetterType;
	GetterType getter;

	typedef function<void(ValueType)> SetterType;
	SetterType setter;

public:
	explicit Property(GetterType gt, SetterType st) : getter(gt), setter(st) {}
	operator ValueType() { return getter(); }
	Property& operator = (ValueType value) { setter(value); return *this; }
};

#define AutoProperty(ValueType, Variable)	\
public: Property<ValueType> Variable;\
private: ValueType var##Variable;\
private: ValueType get##Variable() { return var##Variable; }\
private: void set##Variable(ValueType newValue) { var##Variable = newValue; }\

#define AutoPropertyImpl(Variable, Value)	\
var##Variable(Value), Variable(bind(&A::get##Variable, this), bind(&A::set##Variable, this, placeholders::_1))

class A
{
public:
	// 任务是否可以运行,只读属性
	AutoProperty(bool, CanRun);

public:
	A() : AutoPropertyImpl(CanRun, true)
	{}
};



int main(int argc, char* argv[])
{
	A a;
	bool b = a.CanRun;
	a.CanRun = false;
	
	return 0;
}
上面的这一段代码是可以正确运行的,也就是说我成功了。

PS:本篇文章对应的是自动完成属性的模仿,对于普通属性的模仿,等待我的下一篇文章吧。

本文转载自:http://blog.163.com/lvan100@yeah/blog/static/681172142013101045128499/

梁欢

梁欢

粉丝 5
博文 19
码字总数 0
作品 5
海淀
高级程序员
私信 提问
加载中

评论(0)

[开源世界]从自动导出动态链接库接口看C++的缺点

自动导出动态链接库接口在C++编程中绝对是一件烦人的事情,因为你不得不大量的重复以下几个步骤: 1.加载动态链接库 2.定义导出函数指针定义 3.定义导出函数指针变量 4.从动态链接库中导出函...

梁欢
2013/10/21
548
2
彻底超越MFC----诺基亚的开源GUI库:Qt

在Visual Studio 2003/2005/2008下开发Windows图形界面程序,程序员一直做着抉择:选择.net平台,则意味着需要XP用户安装.net Framework, 而且自己不能手工控制某些代码的优化;选择原生C++...

红薯
2010/05/17
4.6K
8
FFLIB之FFLUA——C++嵌入Lua&扩展Lua利器

摘要: 在使用C++做服务器开发中,经常会使用到脚本技术,Lua是最优秀的嵌入式脚本之一。Lua的轻量、小巧、概念之简单,都使他变得越来越受欢迎。本人也使用过python做嵌入式脚本,二者各有特...

知然
2013/01/27
0
0
Aery的UE4 C++游戏开发之旅(3)蓝图

目录 蓝图 暴露C++至蓝图 蓝图和C++的结合方案 参考 蓝图 大家都知道,蓝图是UE4提供的极其容易上手的一种可视化脚本,更具体的就不说了。 纯靠蓝图搭建的UE4游戏是存在的,但是这类游戏往往...

KillerAery
2019/12/14
0
0
Bjarne Stroustrup's C++ Style and Technique FAQ

Bjarne Stroustrup's C++ Style and Technique FAQ Modified October 4, 2009 Source: http://www2.research.att.com/~bs/bs_faq2.html#void-main ========================================......

长平狐
2013/01/06
206
0

没有更多内容

加载失败,请刷新页面

加载更多

单利模式

花乐天
5分钟前
3
0
生成ssh_key

#生成包含mail的sshkeyssh-keygen -t rsa -C "your_email@example.com"#文件存放路径和文件名Enter file in which to save the key (/Users/teddy/.ssh/id_rsa): /Users/teddy/.ssh/id_r......

人中泰迪
6分钟前
6
0
代理模式

代理模式(Proxy Pattern)是只为其他对象提供一种代理,以控制对这个对象的访问,属于结构行模式。 代理模式一般包含三种角色: 抽象主题角色:抽象主题类的主要职责是声明真实主题与代理的...

xjkvkv
8分钟前
5
0
SQLPro for MySQL for Mac(SQL数据库管理工具) v1.0.315

sqlpro for mysql mac是一款运行在Mac OS平台上的SQL数据库管理工具,轻量级但功能强大的数据库mysql客户端,允许快速和简单的访问MySQL服务器,包括那些驻留在Amazon RDS,方便和快速的连接到...

麦克W
9分钟前
12
0
文件处理及分区管理

{6.shell脚本命令} [1.diff] diff file file1 **比较两个文件的不同 -c **显示周围的行 -u **按照一格式统一输出生成补丁 -r **比较两个目录中文件的不同 patch file file.patch **打补丁 -b...

osc_5ijle82k
17分钟前
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部