MyException - 我的异常网
当前位置:我的异常网» C++ » 对象属性的C++兑现

对象属性的C++兑现

www.MyException.Cn  网友分享于:2013-08-15  浏览:11次
对象属性的C++实现

  高级语言的面向对象编程模型一般都支持“属性”接口,例如 Visual Basic 和 C#。在C#中,通过访问属性,不仅可以存取数据,还可以在存取时执行其它操作,在代码形式上,改变属性值可以写成给变量赋值的形式,例如:Form1.Size = System.Drawing.Size(640,480),而不是调用函数:Form1.SetSize ...(实际上Form没有SetSize函数)。C++语言不支持对象属性,对象的可执行接口只有函数,所以C++里没有“属性”和“方法”的概念。但是通过一些编程的技巧,可以实现一个属性访问器,使 C++ 代码可以具有和 C# 相似的编程风格。

属性访问器模板

  代码如下:

template<typename TObject, typename TProperty>

struct PropAccessor {     TObject* Instance;     PropAccessor(TObject* instance): Instance(instance){}     operator TProperty();     TProperty& operator = (TProperty value); };

  其中:operator TProperty() 用来实现属性的"get"部分,TProperty& operator=(TProperty value) 用来实现属性的"set"部分。

  这个模板是不能直接使用的,两个运算符函数都没有实现,为了可以使用,需要继承模板并实现这两个运算符。这样就定义了一个模拟的“属性”。

属性访问器的实现

  下面是一个具体的实现例子。MeshNode是用于3D场景的模型对象,float3是一个向量类型,表示Mesh在场景中的位置,float4x4是一个矩阵类型,表示Mesh的变换矩阵。演示的代码是MeshNode中的Position属性。

union float3 //一个简单的向量类型。
{
    float m[3];
    struct
    {
        float x, y, z;
    };
    float3()
    {
        for(int i = 0; i < 3; i++)
        {
            this->m[i] = 0.0f;
        }
    };
};
union float4x4 //一个简单的矩阵类型。
{
    float m[16];
    struct
    {
        float _11, _12, _13, _14;
        float _21, _22, _23, _24;
        float _31, _32, _33, _34;
        float _41, _42, _43, _44;
    };
    float4x4()
    {
        for(int i = 0; i < 16; i++)
        {
            this->m[i] = 0.0f;
        }
    };
}; 
class MeshNode
{
public:
    //属性访问器的实现类。这个类直接嵌套在MeshNode,用来实现属性"Position".
    class PROP_Position: public PropAccessor<MeshNode, float3>
    {
        friend class MeshNode;//这个声明使MeshNode可以创建PROP_Position对象,而外部调用者不能创建PROP_Position,因为下面的构造函数是私有。
    private:
        PROP_Position(MeshNode* instance): PropAccessor(instance){};
    public:
        //Property "get":实现了模版中对应的运算符,TProperty被替换为float3。这里只是简单的取得数据,也可以做任何其它操作。
        operator float3()
        {
            float3 rv;
            rv.x = this->Instance->m_WorldMatrix._41;
            rv.y = this->Instance->m_WorldMatrix._42;
            rv.z = this->Instance->m_WorldMatrix._43;
            return rv;
        };
        //Property "set":实现了模板中对应的运算符,TProperty被替换为float3。这里只是简单的保存数据,也可以做任何其它操作。
        float3& operator=(const float3& value)
        {
            this->Instance->m_WorldMatrix._41 = value.x;
            this->Instance->m_WorldMatrix._42 = value.y;
            this->Instance->m_WorldMatrix._43 = value.z;
            return value;
        };
    };
//
private:
    //
    //...
    float4x4 m_WorldMatrix;
    //
public:
    //
    //...
    //

    //属性"Position":取得/设置对象的位置。(前面"PROP_Position"的一堆代码就为了实现这个).
    PROP_Position Position()
    {
        return PROP_Position(this);
    };
};

属性访问器的使用

  有了这些代码,就可以使用"Position"属性了,MeshNode中的Position函数返回的是一个PROP_Position对象,通过这个对象的运算符使代码具有使用属性的风格。例如:

MeshNode* my_mesh = new MeshNode();
float3 my_pos;
my_pos.x = 10.0f;
my_pos.y = 10.0f;
my_pos.z = 10.0f;
my_mesh->Position() = my_pos; //有了使用属性的代码形式。这时调用了"MeshNode::PROP_Position::operator=()"函数。
float3 world_pos = my_mesh->Position(); //和普通C++函数形式相同,但是用到了属性访问器,这时调用了"MeshNode::PROP_Position::operator float3()"函数。

简单总结

  这个属性访问器的优点就不用多说了,主要讨论缺点。具体开发中,可以根据具体情况来决定是否使用它。

  1. 增加了代码量。需要编写多余的代码,为每个属性接口实现一个访问器。

  2. 和传统的"getPosition"和"setPosition"函数相比,通过属性访问器对数据访问,效率略有下降。在"get"过程中,额外的操作是:创建并返回一个访问器对象,调用运算符"operator TProperty()";在"set"过程中,额外的操作是:创建并返回一个访问器对象,调用运算符"TProperty& operator = (TProperty)",且属性值多了一次引用传递。

  3.不能被重载。这样实现的属性不能被重载,如果需要重载,需要更复杂的实现方法。如果不想折腾的话,在程序的设计中就要尽量避免重载属性。

  总体来说对性能影响不大,在不苛刻要求效率的情况下,这些额外的开销可以忽略。只是增加了实现属性访问器的开发工作,如果希望属性可以被重载,需要更多的技巧和工作量,实现方法其实也没有难度,大家可以自由发挥。

文章评论

程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员必看的十大电影
程序员必看的十大电影
程序员和编码员之间的区别
程序员和编码员之间的区别
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员的鄙视链
程序员的鄙视链
那些争议最大的编程观点
那些争议最大的编程观点
代码女神横空出世
代码女神横空出世
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
每天工作4小时的程序员
每天工作4小时的程序员
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
编程语言是女人
编程语言是女人
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
 程序员的样子
程序员的样子
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员应该关注的一些事儿
程序员应该关注的一些事儿
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
我是如何打败拖延症的
我是如何打败拖延症的
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
如何成为一名黑客
如何成为一名黑客
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
10个调试和排错的小建议
10个调试和排错的小建议
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
一个程序员的时间管理
一个程序员的时间管理
我的丈夫是个程序员
我的丈夫是个程序员
为什么程序员都是夜猫子
为什么程序员都是夜猫子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
漫画:程序员的工作
漫画:程序员的工作
Java程序员必看电影
Java程序员必看电影
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
老程序员的下场
老程序员的下场
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
中美印日四国程序员比较
中美印日四国程序员比较
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有