熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

下一代C++:C++/CLI語言的屬性探索

2013-11-13 10:05:06  來源: .NET編程 

  前言
  
  本文展示了歐洲計算機開發商協會正在發展的C++/CLI(一種不同的C++語言它方便開發人員在微軟的NET框架下更容易地開發程序)語言在C++語言上的擴展寫這篇文章的目的並不是要建議標准C++包括這部分擴展也不是對C++/CLI的認可而只是在探討C++/CLI語言在這一領域的發展方向
  
  基礎知識
  
  C++/CLI中的屬性是類似與各種數據成員(有各種操作限制)的可操作實體但是這種操作往往被轉化為調用存取函數(這主要是gettersetter函數)例如
  
  struct Demo {
  property int Val { // 一個非常簡單的整型分級屬性
  int get() const {
  ++Demo::access_count;
  return this>value;
  }
  void set(int v) {
  ++Demo::access_count;
  this>value = v;
  }
  }
  private:
  int value;
  static unsigned long access_count;
  };
  int main() {
  Demo d;
  dVal = ; // 調用set操作函數
  return dVal; //調用get函數
  }
  
  存取函數的名字必須是get 或者是 set函數兩者之中的任何一個都可以被省略但絕不能兩者全省略省略一個存取函數導致只存在一個讀屬性或只存在一個寫屬性屬性的地址是無法獲取的然而存取函數作 為成員函數理所當然地可以被用來產生指向成員的指針常量(例如&Demo::Val::set)
  
  屬性可以使用關鍵字virtual進行聲明這意味者存取操作函數是虛函數純虛屬性函數也是可能存在的例如
  
  struct VirtualProp {
  virtual property int Val = {
  int get() const; // 純虛函數
  virtual void set(int v); //純虛函數這裡關鍵詞virtual是多余的
  }
  //
  };
  
  上述例子顯示了通常情況下遇到的一些簡單的非靜態的分層次的屬性實例C++/CLI文檔包含了大量的概念變化下文將進行解釋
  
  動機
  
  在標准C++的上下文中屬性約定成俗地使用get和set函數文法這種文法將暴露的數據和諧地轉換為封閉地狀態信息在更精細的實時框架上下文中(具體的說是微軟的NET框架)屬性是可以通過映射實時發覺和修改的元素例如現代的GUI庫將它的組件參數聲明為屬性可視化的界面構築工具裝載這些庫使用裝載各種組件的屬性列表並將結果展現到用戶面前當用戶修改了一個屬性存取操作函數將被調用例如這將觸發各種GUI更新事件
  
  屬性變量
  
  除了上述代碼中聲明的簡單的分層屬性C++/CLI還引進了其他幾種類型屬性變量
  
  (一)靜態分層屬性
  
  靜態分層屬性使用關鍵字Static來聲明它們的存取操作函數是靜態的靜態屬性的存取操作與靜態數據成員的存取操作非常一致(例如使用C::P語法來獲取C類的靜態屬性P)
  
  (二)不明顯的分層屬性
  
  一個屬性的定義(即括號內的存取操作函數聲明)可以使用分號來代替在這種情況下get和set存取函數綜合成一個簡單的可以存取操作的屬性值例如C++/CLI定義的一個類如下
  
  struct TrivialProp {
  property int Val;
  };
  
  上述代碼從本質上與下述代碼相同
  
  struct TrivialProp {
  property int Val {
  int get() const { return this>__Val; }
  void set(int v) { this>__Val = v; }
  }
  private:
  int __Val;
  };
  
  (三)指定索引屬性
  
  使用操作數組成員的老語法指定索引可以操作一個數值集合下面的例子顯示了一維索引屬性的操作
  
  struct Demo {
  property int x[std::string] {
  int get(std::string s) const { }
  void set(int v std::string s) { }
  }
  //
  };
  int main() {
  Demo d;
  std::string s(CLI);
  dx[s] = ; // Calls Demo::x::set( s)
  return dx[s]; // Calls Demo::x::get(s)
  }
  
  注意指定索引的屬性不能是靜態變量
  
  多維的索引屬性也是可以的它引入的操作語法與C/C++中數組元素操作方法不太一樣例如
  
  struct Demo {
  property double x[std::string int] {
  double get(std::string s int n) const { }
  void set(double v std::string s int n) { }
  }
  //
  };
  int main() {
  Demo d;
  std::string s(CLI);
  dx[s ] = ; // Calls Demo::x::set( s )
  return dx[s ] != ; // Calls Demo::x::get(s )
  }
  
  後面的這一個例子說明了出現在括號內的操作索引屬性的逗號符號是表達式操作符號而不是一個逗號操作符(下面將討論這種規則帶來的後果)
  
  (四)默認的索引屬性
  
  除了對象被編入偽域外默認的索引屬性與指定的索引屬性非常相象對象本身可以索引(仿佛它自身有一個[]操作成員函數一樣)以前的代碼只要稍微改動一下就可以說明這種變化
  
  struct Demo {
  property double default[std::string int] {
  double get(std::string s int n) const { }
  void set(double v std::string s int n) { }
  }
  //
  };
  int main() {
  Demo d;
  std::string s(CLI);
  d[s ] = ; // Calls Demo::default::set( s )
  return d[s ] != ; // Calls Demo::default::get(s )
  }
  
  請關注關鍵詞default代替屬性名的用法
  
  一些技術性問題
  
  歐洲計算機制造商協會(C++/CLI標准的制訂者)已經研究並解決了引入屬性所帶來的若干問題下面這些內容尤其值得關注
  
  (一)多維索引屬性的操作
  
  p>x[ ]表達式擁有不同的意思這要視成員x是否是屬性(這種情況下逗號分隔兩個索引屬性)或其它成員變量(這種情況下逗號是個操作符號表達式的意思等同於p>x[])而定為了在一個屬性索引中獲取逗號操作符的效果開發人員可以使用圓括號(即p>x[( )])
  
  (注意在依賴模版的表達式中這將產生模糊性並且直到實例化時問題才能得到解決)
  
  (二)屬性名與類型名沖突
  
  微軟NET框架帶有很多包含屬性的類(這些類最初並不是使用C++/CLI來開發的)這些包含的屬性名與屬性類型的名字相同例如
  
  typedef int Color;
  struct Conflict {
  property Color Color { // Property name hides type name
  typename Color get() const;
  void set(typename Color);
  }
  //
  };
  }
  
  為了幫助在這種上下文中書寫代碼C++/CLI計劃添加語法使用關鍵詞typename來標識不標准的類型(特別是屬性查找標志符的過程中將被忽視上述的代碼就以這種新的形式使用typename關鍵詞
  
  (三)重載的索引屬性
  
  索引屬性可以被重載幾個指定索引屬性可以使用同一個名字共存於同一個類中假定它們可以根據屬性的類型來區分開來相似地默認的索引屬性可以使用其他屬性或操作符[]來重載解決兩意性與重載行為的規則已經被建立起來來處理上述情況
  
  (四)保留的成員名字
  
  C++/CLI屬性通過綜合特定的成員來實現這些成員的名義由微軟的NET框架來規定並且必須得到保留
  
  如果一個類包含分層的屬性或指定索引屬性X成員名 get_X 和set_X在類中得到保留(即使屬性僅僅包含一個操作函數也是這樣)相似地如果一個類包含有一個默認的索引屬性類中的成員函數get_Item 和set_Item也將得到保留
From:http://tw.wingwit.com/Article/program/net/201311/12507.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.