如何使用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知識加上咱們的一些編碼技巧,最後咱們用很普通的作法實現了咱們想要的效果。編程有時候給人的感受就是這樣,先要有一個好的概念(如本文中的屬性概念),而後想辦法用咱們熟知的知識需完美地把它實現,這會讓你蠻有成就感!

相關文章
相關標籤/搜索