如何使用C++11实现C#属性概念设计

目录(原创博客,版权全部,转载请注明出处 http://www.cnblogs.com/feng-sc)

      一、概述html

      二、C#属性的概念java

     2.一、简单示例代码介绍C#中的属性ios

     2.二、C++实现效果与C#效果对比(熟悉C#属性读者可今后小节开始)c++

      三、如何使用C++11实现C#属性的概念模型程序员

    3.一、property_rw介绍
    3.二、property_r、property_w介绍编程

    3.三、完整属性测试代码介绍函数

      四、总结oop

一、概述

  在程序员的行业里,有一个有趣的说法,但我以为这个说法在其余行业也一样适用:行业的一流高手都在制定标准和概念,二流高手都在实现标准和概念,三流高手的都在使用标准。性能

  咱们今天来作一次二流的高手作的事情:一、为c++引入一个概念标准;二、用c++实现这个概念。测试

二、C#属性的概念

  本想略过对C#属性的介绍,但考虑到读者可能没使用过C#,也不知道C#的属性到底有什么用,所以仍是稍微从使用的角度先解释一下C#中属性的概念(若是您对属性已经足够了解,可直接跳过本章或直接从下面第2点的“C++实现效果与C#效果对比”开始)。

  一下内容包含以下部分:

一、简单示例代码介绍C#中的属性;

二、C++实现效果与C#效果对比;

  

  一、简单示例代码介绍C#中的属性


  咱们来看第一段C#代码:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
class
TestDemo { public String Name { get; set; } } class Program { static void Main(string[] args) { TestDemo test = new TestDemo(); test.Name = "test"; System.Console.WriteLine(test.Name); } }

  上面代码中,咱们建立了一个String类型的属性Name,这个时候咱们,咱们的属性其实跟一个成员变量没啥区别,只是一个成员变量罢了。

  另外,还须要读者了解的是,属性里的get和set分别控制属性的读写权限:

  一、若是只有get,那么Name为只读模式;

  二、若是只有set,那么Name为只写模式;

  只读模式示例代码:

 1 //示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
 2 class TestDemo
 3 {
 4     public String Name
 5     {
 6         get;
 7     }
 8 }
 9 class Program
10 {
11     static void Main(string[] args)
12     {
13         TestDemo test = new TestDemo();
14         test.Name = "test";//只读属性,赋值不容许,编译出错
15 System.Console.WriteLine(test.Name); 16 } 17 }

  只写模式示例代码:

 1 //示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
 2 class TestDemo
 3 {
 4     public String Name
 5     {
 6         set;
 7     }
 8 }
 9 class Program
10 {
11     static void Main(string[] args)
12     {
13         TestDemo test = new TestDemo();
14         test.Name = "test";
15         System.Console.WriteLine(test.Name);  //只写模式,test.Name取值不容许,编译失败
16     }
17 }

  咱们再来看一个复杂点的例子:

 1 //示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
 2 class TestDemo
 3 {
 4     public String Name
 5     {
 6         get
 7         {
 8             return _name;
 9         }
10         set
11         {
12             _name = value;
13             TestWork();
14         }
15     }
16     public void TestWork()
17     {
18         System.Console.WriteLine(_name);
19     }
20 
21     private String _name;
22 }
23 class Program
24 {
25     static void Main(string[] args)
26     {
27         TestDemo test = new TestDemo();
28         test.Name = "test";
29     }
30 }

  以上代码中,咱们运行到第28行的时候,会进入到第10行,最终运行结果打印出“test”。

  是的,其实很简单,若是没有属性,咱们彻底能够用一个私有的成员函数,而后为每一个成员函数添加一个get和set的方法(java下的一般作法),以下代码中的TestDemo彻底能实现上面代码中属性的作法:

 1 //示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
 2 class TestDemo
 3 {
 4     public String GetName()
 5     {
 6         return _name;
 7     }
 8     public void SetName(String value)
 9     {
10         _name = value;
11         TestWork();
12     }
13     public void TestWork()
14     {
15         System.Console.WriteLine(_name);
16     }
17 
18     private String _name;
19 }
……

  OK,那为何要有属性呢?

  其实追求的真是一种书写方法吧,属性能让咱们像访问成员变量同样访问直接赋值和取值,同时,在赋值和取值的时候,能根据需求调用相应的内部实现函数。

  

  二、C++实现效果与C#效果对比


        

  请读者对比下左右两边的属性Name的定义方式,C#里面的get和set方法在C++11实现中,使用了property_getter和property_setter实现,property_getter和property_setter中代码的实现方式与C#均一致。

  OK,看完属性效果比较,若是您以为对你的胃口,那么能够继续往下看,下面会有关于proerty_rw更详细的说明。

 

三、如何使用C++11实现C#属性的概念模式

  本章咱们将一步步介绍C++11实现属性三种形式分别是:

一、property_rw :对应C#的读写模式(get和set均有)

二、property_r :对应C#的只读模式(没有set)

三、property_w  :对应C#的只写模式(没有get)

  一、property_rw介绍


  property_rw的实现代码很简单,但须要你们对C++11中的std::function和lamda表达式有所了解,若是您不是很了解或在下面介绍中以为难懂,能够先看看我以前写的关于C++11的总结文章:【干货】C++11经常使用特性的使用经验总结,对您理解本章内容会有帮助。

  proerty_rw源码:

 1 //示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
 2 #include<functional>
 3 #define property_setter(variableType) [&](variableType value)
 4 #define property_getter(variableType) [&]()->variableType
 5 template <typename ValueType>
 6 class property_rw
 7 {
 8 public:
 9     typedef std::function<void(ValueType value)> Setter;
10     typedef std::function<ValueType(void)> Getter;
11     explicit property_rw(Setter setter, Getter getter) : m_setter(setter), m_getter(getter) {}
12     property_rw& operator=(ValueType value)
13     {
14         this->value = value;
15         m_setter(this->value);
16         return *this;
17     }
18     property_rw& operator=(const property_rw & instance)
19     {
20         this->value = instance.m_getter();
21         m_setter(this->value);
22         return *this;
23     }
24     operator ValueType()
25     {
26         return m_getter();
27     }
28 private:
29     ValueType value;
30     Setter m_setter;
31     Getter m_getter;
32 };

  上面代码咱们能够看出,property_rw是一个模板类,ValueType为属性的类型名,所以你们能够想到,咱们的属性实际上是一个类对象。

  所以,咱们来看一个最简单的使用示例:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
#include<string> #include"property.h" class TestDemo { public: property_rw<std::string> Name; };

  须要注意:#include<string>须要放在#include"property.h"以前,同理,其余非基本数据类型引用头文件均需如此,这主要是因为proerty.h内部宏定义的property_setter和property_getter所致使,要保持属性的书写风格,目前暂时没有很好的解决这个问题。

  上面的代码没法编译经过,但咱们先看看形式,咱们定义了一个string类型的属性Name。

  从proerty_rw的构造函数看explicit property_rw(Setter setter, Getter getter),咱们定义这个属性,须要给这个属性赋值两个参数,分别为Setter和Getter。Getter和Setter类型分别为std::function定义的两个可执行对象类型。在【干货】C++11经常使用特性的使用经验总结文章中,咱们介绍了std::function定义的可执行对象能够有三种形式的赋值,分别是:

  一、同形式(返回值和参数相同)函数指针;

  二、同形式的类成员函数;

  三、同形式的lamda表达式函数;

  为了统一外面的使用形式,咱们使用宏的方式定义(property_rw源码第三、4行)property_getter和proerty_setter,该宏定义实际上是限制外部使用lamda表达式方式(固然,这没能从编译源头限制,其实外部仍是可使用第一、2两种方式)。咱们来看下property_getter和proerty_setter的定义:

#define property_setter(variableType) [&](variableType value)  //定义lamda表达式的头部,[&]表示对定义范围内的变量取值权限为引用形式,参数为variableType
#define property_getter(variableType) [&]()->variableType    //property_getter的lamda表达式返回值为variableType

  明白了property_getter和proerty_setter的定义,咱们来看下Name的初始化:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
class
TestDemo { public: property_rw<std::string> Name = property_rw<std::string>( property_setter(std::string) { }, property_getter(std::string) { return "test"; } ); };

  这个时候咱们来看Name的初始化就很是清晰了,其实就是给property_rw构造函数传递了两个lamda表达式定义的函数,通过咱们的宏封装,使咱们的属性使用风格看起来与C#形式很像。

  咱们再来看看property_rw中的函数,控制读取属性的函数:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
property_rw& operator=(ValueType value) { this->value = value; m_setter(this->value); return *this; } property_rw& operator=(const property_rw & instance) { this->value = instance.m_getter(); m_setter(this->value); return *this; }

  加入咱们如今有两个属性string类型的属性,名字分别为Name1,Name2,那么何时会调用上面两个函数呢?

TestDemo test;
test.Name1 = "test";   //调用第一个operator=()函数
test.Name2 = test.Name1; //调用第二个operator=()函数

  property_rw中控制写熟悉的函数:

operator ValueType()
{
    return m_getter();
}

  示例:

TestDemo test;
test.Name = "test";
std::string str = test.Name //调用写属性控制函数

  小结:

  property_rw的模板类实现简单吧,没有太多的逻辑代码,都是普通的类设计而已,关键须要你们有一些编码技巧。

  

  二、property_r、property_w介绍


  property_r和property_w就更加简单了,我么只须要把property_rw中的控制读或控制写的属性函数去掉,就能够变成只读或只写的属性类型。

  property_r源码:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
template <typename ValueType> class property_r { public: typedef std::function<void(ValueType value)> Setter; typedef std::function<ValueType(void)> Getter; explicit property_r(Getter getter) : m_getter(getter) {} operator ValueType() { return m_getter(); } private: ValueType value; Getter m_getter; };

  property_w源码:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
template <typename ValueType> class property_w { public: typedef std::function<void(ValueType value)> Setter; explicit property_w(Setter setter) : m_setter(setter) {} property_w& operator=(ValueType value) { this->value = value; m_setter(this->value); return *this; } property_w& operator=(const property_w & instance) { this->value = instance.m_getter(); m_setter(this->value); return *this; } private: ValueType value; Setter m_setter; };

   property_r和property_w就没有什么能够介绍的了,基本和property_rw相似。

 

  三、完整属性测试代码介绍


  下面是一个比较完整的测试例子:

//示例代码1.0 http://www.cnblogs.com/feng-sc/p/5742689.html
#include<iostream> #include<string> #include"property.h" class TestDemo { public: property_rw<std::string> Name = property_rw<std::string>( property_setter(std::string) { m_rw_name = value; }, property_getter(std::string) { return m_rw_name; } ); property_r<std::string> ReadOnlyName = property_r<std::string>( property_getter(std::string) { return m_readonly_name; } ); property_w<std::string> WriteOnlyName = property_w<std::string>( property_setter(std::string) { m_writeonly_name = value; TestWork(); } ); void TestWork() { std::cout <<"TestWork()::m_writeonly_name--"<< m_writeonly_name << std::endl; } private: std::string m_rw_name; std::string m_readonly_name = "I m read only name"; std::string m_writeonly_name = ""; }; int main() { TestDemo test; test.Name = "This is test name!"; std::string str = test.Name; std::string readonly = test.ReadOnlyName; std::cout << "Test read and write,Name:" << str << std::endl; std::cout << "Test readonly, msg:" << readonly << std::endl; test.WriteOnlyName = "This is write only property!"; }

  运行结果:

  

 

四、总结

  本文咱们首先介绍了C#属性概念,以及为何使用属性,再一步一步引出咱们如何使用C++11实现C#属性的效果。整篇文章所述没有太多逻辑的问题,单纯用咱们所熟知的C++11知识加上咱们的一些编码技巧,最后咱们用很普通的作法实现了咱们想要的效果。编程有时候给人的感受就是这样,先要有一个好的概念(如本文中的属性概念),而后想办法用咱们熟知的知识需完美地把它实现,这会让你蛮有成就感!

相关文章
相关标签/搜索