分享
 
 
 

在C++中利用模板实现 data variant(propery)

王朝c/c++·作者佚名  2006-07-05
窄屏简体版  字體: |||超大  

在C++Builder, 可以通过CB的扩展语法__property()来实现对象的Property。但这个方法必需有编译器的支持,脱离了CB的编译环境就无法使用。同样的,在VC6.0以上的版本中,也实现了__declspec(property)这样一个语法来实现property.它除了跟CB 中的perperty一样,在跨平台方面有局限性以外,而且他不支持多态。 下面的例子可以说明:

class M

{

private:

int v;

virtual int Get()

{

return v;

}

virtual void Set(int x)

{

v = x;

}

public:

__declspec(property(get=Get,put=Set)) int XValue;

};

class MM : public M

{

virtual int Get()

{

return v+3;

}

virtual void Set(int x)

{

v = x -3;

}

};

MM m;

m.XValue = 3; //实际上调用的是M::Set(),而不是MM::Set()

int v = m.XValue; //实际上调用的是M::Get(), 而不是MM:Get();

为什么呢?因为在编译器进行编译的时候,已经将这个property跟 M::Get(),M::Set()邦定在了一起。

鉴于上面所述,我们提出我们目标:

1. 要实现Property,并且不依赖于某一个开发平台,只要是当前流行的C++编译器都可以编译通过。

2. 必须使这种Property的实现方法符合OOP的法则。

只有达到以上两点,才能使我们的方法有实用性。

下面我们利用C++的模板方法来实现Property. 这个方法未必是最好的,而且在实际使用的时候还会是有问题的。但也算是学习一下C++的Template了。

首先来看看Property的基本实现原理。在C++语法中,是没有Property这样的语法的。在C++中,Property就相当于类成员变量,我们可以把成员变量暴露在Public域,这样我们可以任意操作他,而不用很麻烦的去调用某一个操作函数(看上去就象在VB中操作对象的Property一样)。但实际上这是一种很不安全的方法,因为我们失去了对这个成员变量的控制,那将会发生很多意料不到的事情。 因此在C++中,Property的实现都是通过成员函数来模拟实现的。比如:

class A

{

private:

int x;

public:

void get_X(int& v);

void put_X(int v);

}

类A中的成员函数X,就是通过get_X()和put_X()这两个函数来实现访问的。这将保证变量x尽量的处于我们的保护之中(可以在get_X,put_X中写入我们对x的保护代码)。

那么能否通过某一种方法,来隐藏对get_和put_函数的调用,而类似于:

A.X_Value = 3; //其实是间接调用A.put_X(3)

int a = A.X_Value; //其实是间接调用A.get_X();

这样的语法呢?

可以通过C++的模板技术来实现。要实现这样的语法,我们需要一个代理模板类, 在这个模板类中,我们重载操作符"=", 在这个重载的operator =()函数中,我们调用宿主对象的put_X()函数,把值传入. 然后我们还要重载属性值类型的操作符, 比如属性值的类型是 string ,则我们要重载一个叫string的操作符, 并在 operator string()中调用宿主对象的get_X()函数,把值传出去.

下面是例子代码

#include <stdio.h>

#include <string>

using namespace std;

template<class ClassName , typename ParamType>

class Property

{

public:

typedef void (ClassName::*Get)(ParamType& ) ; //定义一个指向实际类中进行数据操作的函数指针类型 Get,和 Set

typedef void (ClassName::*Set)(ParamType& ) ;

Property()

{

};

Property( Get pGet , Set pSet ,ClassName* pHost ):m_pfnGet(pGet),m_pfnSet(pSet),m_pHost(pHost)

{

};

operator ParamType()

{

ParamType v;

(m_pHost->*m_pfnGet)(v);

return v;

};

ParamType operator = (ParamType v)

{

(m_pHost->*m_pfnSet)(v);

return v;

};

private:

Get m_pfnGet; //保存设置函数的指针

Set m_pfnSet; //保存获取函数的指针

ClassName* m_pHost; //保存宿主对象到指针

};

class CTestClass

{

protected:

int v;

virtual void SetValue(int& x )

{

v = x;

};

virtual void GetValue(int& x )

{

x = v;

};

public:

Property<CTestClass,int> Value;

CTestClass():Value((Property<CTestClass,int>::Get)&CTestClass::GetValue,

(Property<CTestClass,int>::Set)&CTestClass::SetValue,

this

)

{

}

};

//属性值为C++对象的例子

class CTestClass2

{

private:

string m_str;

void SetValue(string& s)

{

m_str = s;

};

void GetValue(string& s)

{

s = m_str;

}

public:

Property<CTestClass2,string> Value;

CTestClass2():Value((Property<CTestClass2,string>::Get)&CTestClass2::GetValue,

(Property<CTestClass2,string>::Set)&CTestClass2::SetValue,

this

)

{

}

};

//测试子类的函数能否正确调用

class CChild : public CTestClass

{

protected:

void SetValue(int& x)

{

v = x + 5;

}

};

int main(int argc, char* argv[])

{

CTestClass m;

m.Value = 5;

printf("m.value is %d\n",(int)m.Value);

CChild n;

n.Value = 5;

printf("n.value is %d\n",(int)n.Value);

CTestClass2 o;

o.Value = "hello,propery!";

printf("o.value is %s\n",((string)o.Value).c_str());

getchar();

return 0;

}

使用G++进行编译.

g++ property.cpp -o property

运行 ./property

输出:

m.value is 5

n.value is 10

o.value is hello,propery!

因为我们传达给代理类的宿主对象的实际运行指针(this), 所以即使是宿主对象的set,get函数是虚拟函数,我们也能获取到函数的地址,进行调用. 但是这个方法在获取属性值时还是有些缺陷的, 就是必须显式的声明调用类型. 比如上例中, printf("m.value is %d\n",(int)m.Value); 必须在m.Value 前加(int), 否则编译器就不知道m.Value是什么类型,就会报错(也许有的编译器能够自动用Property类的opreator int 去转换).

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有