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

[C/C++]属性的秘密——C++仿C#的属性实作 
在上一篇文章中,我实现了C++的属性,但是总感觉哪里还是不对劲 ,嗯,对,是哪个this,属性初始化的时候VS会提示this在没初始化完毕就被使用,虽然我知道this在这个时候可以被使用,但是让编译器产生这么多的警告信息,看着也还是不爽。

今天突然跑出一个灵感来,何不用内部类试试呢?这样就可以隐藏this指针了。说干就干。下面就是成果了:

/*
	 * 属性实现需要的内部类
	 */

	#define variableproperty(ClassType, ValueType, GetAccessor, SetAccessor, Variable) \
		public :\
			class Variable##Property\
			{\
			GetAccessor:\
				operator ValueType()\
				{\
					return Get##ClassType()->get##Variable();\
				}\
			SetAccessor:\
				Variable##Property& operator = (ValueType value) \
				{\
					Get##ClassType()->set##Variable(value);\
					return *this;\
				}\
			private:\
				inline ClassType* Get##ClassType()\
				{\
					return ((ClassType*)((unsigned char*)this - offsetof(ClassType, Variable)));\
				}\
			}Variable;\


	/*
	* 自动实现的属性,在类内部自动实现原始成员变量定义及其访问函数:
	* 原始变量为var##Variable,当属性为非可读写时,类内部可以访问它;
	* 访问函数为get##Variable和set##Variable,这俩函数不能被外部访问.
	*/

	#define autoproperty(ClassType, ValueType, GetAccessor, SetAccessor, Variable) \
		variableproperty(ClassType, ValueType, GetAccessor, SetAccessor, Variable) \
		private: ValueType var##Variable;\
		private: ValueType get##Variable() { return var##Variable; }\
		private: void set##Variable(ValueType newValue) { var##Variable = newValue; }

	#define autopropertyinit(Variable, InitValue) var##Variable(InitValue)


	/*
	* 一般(委托)属性,能够自定义getter和setter的名称.
	*/

	#define customproperty(ClassType, ValueType, GetAccessor, Getter, SetAccessor, Setter, Variable) \
		variableproperty(ClassType, ValueType, GetAccessor, SetAccessor, Variable)\
		private: ValueType get##Variable() { return Getter(); }\
		private: void set##Variable(ValueType newValue) { Setter(newValue); }


	/*
	 * 一般(委托)属性,使用固定格式的getter和setter:Variable##Getter/Variable##Setter.
	 */

	#define simpleproperty(ClassType, ValueType, GetAccessor, SetAccessor, Variable) \
		customproperty(ClassType, ValueType, GetAccessor, Variable##Getter, SetAccessor, Variable##Setter, Variable)
使用起来也算不上复杂:
int gValue = 0;
int gOtherValue = 1;

struct CValue
{
	int a;
	short b;
}tCValue;

struct DValue
{
	int a;
	short b;
	DValue(int t) : a(t), b(0) {}
	DValue& operator= (DValue& t) { a = t.a; return *this; }
}tDValue(0);

class A
{
public:
	// 基本数据类型
	simpleproperty(A, int, public, public, a);
	simpleproperty(A, double, public, public, b);

	// 指针类型
	autoproperty(A, int*, public, public, c);
	autoproperty(A, void*, public, public, d);

	// 引用类型
	autoproperty(A, int&, public, public, e);

	// 自定义类型
	autoproperty(A, CValue, public, public, f);
	autoproperty(A, DValue, public, public, g);


public:
	A() : autopropertyinit(c, new int(1))
		, autopropertyinit(d, nullptr)
		, autopropertyinit(e, gValue)
		, autopropertyinit(f, tCValue)
		, autopropertyinit(g, tDValue)
	{}

	~A(){}

	int aGetter()
	{
		return 0;
	}

	void aSetter(int thisV)
	{
	}

	double bGetter()
	{
		return 1;
	}

	void bSetter(double thisV)
	{
	}
};

void testProperty()
{
	tCValue.a = 10;
	tCValue.b = 9;

	A a;
	a.a = 9;
	a.b = 7.10;
	a.c = new int(2);
	a.d = new int(3);
	
	// 引用类型,只能传递引用?
	a.e = gOtherValue;

	tCValue.a = 9;
	tCValue.b = 10;
	a.f = tCValue;

	a.g = DValue(9);
}
最后说一下,为什么要使用 autopropertyinit吧?本来可以让内部类实现一个带参数的构造函数,但是如果属性是自定义类型或者引用类型,就需要对原始变量重新初始化一次,反而麻烦了,不如再加个宏,只针对原始值进行初始化反而简单。

大家可以比较一下前后两种方法的优劣:
第一种用委托实现的方式总体来说要占用更多的存储空间;
第二种用内部类实现的方式总体来说会造成大量的内部类。
... ...

转载于:https://my.oschina.net/lvan100/blog/175401

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值