程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> 下一代C++:C++/CLI語言的屬性探索

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

編輯:vc教程
前言:

  本文展示了歐洲計算機開發商協會正在發展的C++/CLI(一種不同的C++語言,它方便開發人員在微軟的.NET框架下更容易地開發程序)語言在C++語言上的擴展。寫這篇文章的目的並不是要建議標准C++包括這部分擴展,也不是對C++/CLI的認可,而只是在探討C++/CLI語言在這一領域的發展方向。

  一、基礎知識

  C++/CLI中的屬性是類似與各種數據成員(有各種操作限制)的可操作實體,但是這種操作往往被轉化為調用存取函數(這主要是"getter"和"setter"函數)。例如:

struct Demo1 {
  property int Val { // 一個非常簡單的整型、分級屬性。
   int get() const {
    ++Demo1::access_count;
    return this->value;
  }
  void set(int v) {
   ++Demo1::access_count;
   this->value = v;
  }
}
private:
  int value;
  static unsigned long access_count;
};
int main() {
  Demo1 d;
  d.Val = 3; // 調用"set"操作函數。
  return d.Val; //調用"get"函數。
}
  存取函數的名字必須是get 或者是 set函數,兩者之中的任何一個都可以被省略,但絕不能兩者全省略。省略一個存取函數導致只存在一個讀屬性或只存在一個寫屬性。屬性的地址是無法獲取的,然而,存取函數作 為成員函數理所當然地可以被用來產生指向成員的指針常量(例如:&Demo1::Val::set)。

  屬性可以使用關鍵字"virtual"進行聲明,這意味者存取操作函數是虛函數,純虛屬性函數也是可能存在的,例如:

struct VirtualProp {
  virtual property int Val = 0 {
   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 Demo2 {
  property int x[std::string] {
   int get(std::string s) const { ... }
   void set(int v, std::string s) { ... }
  }
  // ...
};
int main() {
  Demo2 d;
  std::string s("CLI");
  d.x[s] = 3; // Calls Demo2::x::set(3, s)
  return d.x[s]; // Calls Demo2::x::get(s)
}
  注意,指定索引的屬性不能是靜態變量。

  多維的索引屬性也是可以的,它引入的操作語法與C/C++中數組元素操作方法不太一樣,例如:

struct Demo3 {
  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() {
  Demo3 d;
  std::string s("CLI");
  d.x[s, 7] = 42.0; // Calls Demo3::x::set(42.0, s, 7)
  return d.x[s, 7] != 42.0; // Calls Demo3::x::get(s, 7)
}
  後面的這一個例子說明了出現在括號內的操作索引屬性的逗號符號是表達式操作符號,而不是一個逗號操作符。(下面將討論這種規則帶來的後果)。

  (四)默認的索引屬性

  除了對象被編入偽域外,默認的索引屬性與指定的索引屬性非常相象,對象本身可以索引(仿佛它自身有一個[]操作成員函數一樣),以前的代碼只要稍微改動一下就可以說明這種變化。

struct Demo4 {
  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() {
  Demo4 d;
  std::string s("CLI");
  d[s, 7] = 42.0; // Calls Demo4::default::set(42.0, s, 7)
  return d[s, 7] != 42.0; // Calls Demo4::default::get(s, 7)
}
  請關注關鍵詞"default"代替屬性名的用法。

四、一些技術性問題

  歐洲計算機制造商協會(C++/CLI標准的制訂者)已經研究並解決了引入屬性所帶來的若干問題,下面這些內容尤其值得關注。

  (一)多維索引屬性的操作

  p->x[2, 3]表達式擁有不同的意思,這要視成員x是否是屬性(這種情況下逗號分隔兩個索引屬性)或其它成員變量(這種情況下逗號是個操作符號,表達式的意思等同於p->x[3])而定。為了在一個屬性索引中獲取逗號操作符的效果,開發人員可以使用圓括號(即p->x[(2, 3)])。

  (注意,在依賴模版的表達式中,這將產生模糊性,並且直到實例化時問題才能得到解決)

  (二)屬性名與類型名沖突

  微軟.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也將得到保留。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved