为数据结构添加setProperty和getProperty
为手头游戏项目写编器,关联编器和游戏中的游戏对象的属性成了一个不小的问题,经过多经改写总算有一个相对好点的方案了,如果大家有更好的解决方案,请指点:
myProperty.h
[cpp]
// 王智泉
#ifndef __myProperty__H__
#define __myProperty__H__
#include <string>
#include <vector>
// @注意: 以下的宏只能在CPP文件中使用
/* 定义一个属性
@param ownerClass: 宿主类
@param propertyName: 属性名
@param bindVar: 邦定的变量
@param defaultVal: 默认值
@param describe: 描述
**/
// =================================================================
#define myDEF_PROPERTY(ownerClass, propertyName, bindVar, describe)/
class ownerClass##bindVar##Pty : public myProperty/
{/
public:/
ownerClass##bindVar##Pty():myProperty(propertyName, describe){}/
virtual void setter(myPropertySet* owner, const std::string& val)/
{/
str2val(val, &(static_cast<ownerClass*>(owner)->##bindVar));/
}/
virtual std::string getter(const myPropertySet* owner)/
{/
return val2str(static_cast<const ownerClass*>(owner)->##bindVar);/
}/
virtual std::string getValueType(const myPropertySet* owner)/
{/
return getvalType( static_cast<const ownerClass*>(owner)->##bindVar );/
}/
};/
static ownerClass##bindVar##Pty s_pty##ownerClass##bindVar;
// 清空属性可能的值
#define myClearPropertyPossVals(ownerClass, bindVar)/
s_pty##ownerClass##bindVar._possibleVal.clear();
// 为属性增加可选的值
#define myAddPropertyPossVal(ownerClass, bindVar, possibleVal)/
s_pty##ownerClass##bindVar._possibleVal.push_back(possibleVal);
/* 注册属性
@param ownerClass: 类名
@param propertyName: 属性名
**/
#define myRegisterProperty(ownerClass, bindVar)/
registerProperty_impl(&s_pty##ownerClass##bindVar);/
s_pty##ownerClass##bindVar._defaultVal = s_pty##ownerClass##bindVar.val2str(bindVar);
// 属性类
// =====================================================================
class myPropertySet;
class myProperty
{
public:
/* 构造函数
@param name: 属性名
@param valType: 数据类型
@param describe: 描述
**/
myProperty(const std::string& name, const std::string& describe)
: _name(name)
, _describe(describe)
{}
virtual ~myProperty(){}
/* 设置属性
@param owner: 该属性的宿主(myPorpertySet的子类)
@param val: 该属性对应的值
**/
virtual void setter(myPropertySet* owner, const std::string& val) = 0;
/* 获得属性
@param owner: 该属性的宿主(myPorpertySet的子类)
**/
virtual std::string getter(const myPropertySet* owner) = 0;
/* 获得属性的数据类型
@param owner: 宿主
@return: 返回数据类型的名称(int, float, bool, string, ...)
**/
virtual std::string getValueType(const myPropertySet* owner) = 0;
public:
// 将字符串转化成其它类型
void str2val(const std::string& str, int* val) { *val = atoi(str.c_str());}
void str2val(const std::string& str, float* val){ *val = (float)atof(str.c_str()); }
void str2val(const std::string& str, bool* val){ *val = str == "TRUE"; }
void str2val(const std::string& str, std::string* val){ *val = str; }
// 奖其它类型转化成字符串
std::string val2str(int val) {char str[128] = {0}; sprintf(str, "%d", val); return str; }
std::string val2str(float val) {char str[128] = {0}; sprintf(str, "%.2f", val); return str; }
std::string val2str(bool val) { return val ? "TRUE" : "FALSE"; }
std::string val2str(const std::string& val){ return val; }
std::string val2str(double val){ return val2str((float)val); }
// 获得属性的数据类型
std::string getvalType(int val) {return "int";}
std::string getvalType(float val) {return "float";}
std::string getvalType(bool val) {return "bool";}
std::string getvalType(std::string val) {return "string";}
public:
std::string _name; // 属性的名称
std::string _defaultVal; // 默认值
std::string _describe; // 描述
std::vector<std::string> _possibleVal; // 可用的值
};
#endif
myProperty.cpp
[cpp]
#include "myProperty.h"
myPropertySet.h
[cpp]
// 王智泉
// 属性集
#ifndef __myPropertySet__H__
#define __myPropertySet__H__
#include <string>
#include <map>
// 关闭自动排序(还未用)
template<class T>
struct DisableCompare
{
bool operator()(const T& lhs, const T& rhs) const
{
return true;
}
bool operator<(const T& rhs) const
{
return true;
}
};
// 属性集
// ======================================================================
class myProperty;
class myPropertySet
{
public:
typedef std::map<std::string, myProperty*> PropertyList;
myPropertySet(void);
virtual ~myPropertySet(void);
/* 注册属性
@param pty: 属性
**/
void registerProperty_impl(myProperty* pty);
/* 设置属性
@param name: 属性名
@param val: 属性值
**/
void setProperty(const std::string& name, const std::string& val);
/* 获得属性值信息
@param name: 属性名
@return: 返回属性名对应的值
**/
std::string getProperty(const std::string& name) const;
/* 获得属性
@param name: 属性名
@return: 返回属性名对应的属性指针
*/
myProperty* getPropertyPtr(const std::string& name);
/* 获得指定属性的数据类型
@param name: 属性名
@return: 返回指定属性的数据类型
**/
std::string getPropertyValueType(const std::string& name) const;
public:
PropertyList _ptysList;
};
#endif
myPropertySet.cpp
[cpp]
#include "myPropertySet.h"
#include "myProperty.h"
#include <assert.h>
// ================================================================
myPropertySet::myPropertySet(void)
{
}
// ================================================================
myPropertySet::~myPropertySet(void)
{
}
// ================================================================
void myPropertySet::registerProperty_impl(myProperty * pty)
{
_ptysList[pty->_name] = pty;
}
// ================================================================
void myPropertySet::setProperty(const std::string& name, const std::string& val)
{
myPropertySet::PropertyList::iterator pos = _ptysList.find(name);
if (pos != _ptysList.end())
{
pos->second->setter(this, val);
}
}
// ================================================================
std::string myPropertySet::getProperty(const std::string& name) const
{
myPropertySet::PropertyList::const_iterator pos = _ptysList.find(name);
assert(pos != _ptysList.end());
return pos->second->getter(this);
}
// ================================================================
myProperty* myPropertySet::getPropertyPtr(const std::string& name)
{
myPropertySet::PropertyList::const_iterator pos = _ptysList.find(name);
if (pos != _ptysList.end())
return pos->second;
return NULL;
}
// ================================================================
std::string myPropertySet::getPropertyValueType(const std::string& name) const
{
myPropertySet::PropertyList::const_iterator pos = _ptysList.find(name);
assert(pos != _ptysList.end());
return pos->second->getValueType(this);
}
myMain.cpp
[cpp]
// 王智泉
#include "myPropertySet.h"
#include "myProperty.h"
#include <iostream>
class myTest : public myPropertySet
{
public:
myTest();
int _intVal;
float _floatVal;
std::string _strVal;
bool _boolVal;
};
// 定义属性
myDEF_PROPERTY(myTest, "IntValue", _intVal, "这是整型");
myDEF_PROPERTY(myTest, "FloatValue", _floatVal, "这是浮点型");
myDEF_PROPERTY(myTest, "StringValue", _strVal, "这是字符串");
myDEF_PROPERTY(myTest, "BOOLValue", _boolVal, "这是布尔型");
myTest::myTest()
{
// 注册属性,一定人先调用myDEF_PROPERTY定义对应的属性
myRegisterProperty(myTest, _intVal);
myRegisterProperty(myTest, _floatVal);
myRegisterProperty(myTest, _strVal);
myRegisterProperty(myTest, _boolVal);
}
int main()
{
myTest test;
test.setProperty("IntValue", "10");
test.setProperty("FloatValue", "10");
test.setProperty("StringValue", "我叫王智泉,哈哈....");
test.setProperty("BOOLValue", "TRUE");
std::cout << "IntValue:" << test._intVal << "/nFloatValue:" << test._floatVal << "/nStringValue:" << test._strVal << "/nBOOLValue:" << test._boolVal << std::endl;
test._intVal = 100;
test._floatVal = 100.0f;
test._strVal = "Are you a programming monkey?";
test._boolVal = false;
std::cout << "/nIntValue:" << test.getProperty("IntValue") << "/nFloatValue:" << test.getProperty("FloatValue") << "/nStringValue:" << test.getProperty("StringValue") << "/nBOOLValue:" << test.getProperty("BOOLValue") << std::endl;
return 0;
}
输出结果:
IntValue:10
FloatValue:10
StringValue:我叫王智泉,哈哈....
BOOLValue:1
IntValue:100
FloatValue:100.00
StringValue:Are you a programming monkey?
BOOLValue:FALSE