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

C++/CLI基本數據類型探索

2022-06-13   來源: ASP編程 

  C++/CLI所支持的基本類型例如intdoublebool等在某些方面可以說是沿襲了ISOC++中的類型——同樣的用法會在C++/CLI中得到同樣的結果例如加法或者賦值操作但是C++/CLI也為這些基本類型引入了一些新的東西
  
  在通用類型系統(CTS)中每一個基本類型都在System命名空間中存在一個對應的類(見表例如int實際上完全等價於System::Int我們可以使用二者中的任何一個來聲明一個整數
  
  int ival = ;
  Int ival = ;
  
  出於移植性的考慮在使用這些基本類型時我們推薦大家使用內建的關鍵詞而非System命名空間中的類名
  

  
基本類型和它們在System命名空間中對應的類

  
  對於System命名空間中類的公有靜態成員我們既可以通過內建的關鍵字也可以通過System命名空間中的類名來訪問例如為了獲取一個數值類型的取值范圍我們可以直接使用內建的關鍵字來訪問其靜態屬性MaxValue和MinValue
  
  int imaxval = int::MaxValue;
  int iminval = Int::MinValue;
  
  每個數值類型都支持一個名為Parse的成員函數用以將一個字符串轉化為其所表示的數值例如給定下面的字符串
  
  String^ bonus = $ ;
  
  調用Parse會將myBonus初始化為
  
  double myBonus = double::Parse( bonus ns );
  
  其中ns表示對一些NumberStyles枚舉類型取位或(bitwise or)運算的結果NumberStyles是位於System::Globalization命名空間中的一個枚舉類型用於表征對空白貨幣符號小數點或者逗號等的處理看下面的代碼
  
  using namespace System;
  using namespace System::Globalization;
  
  double bonusString( String^ bonus )
  {
  NumberStyles ns = NumberStyles::AllowLeadingWhite;
  ns |= NumberStyles::AllowCurrencySymbol;
  ns |= NumberStyles::AllowThousands;
  ns |= NumberStyles::AllowDecimalPoint;
  
  return double::Parse( bonus ns );
  
  }
  
  我們也可以使用轉型符號來在類型間進行顯式的轉換
  
  int ival = ( int ) myBonus;
  
  或者使用System::Convert類的一些轉換方法例如ToDouble() ToInt() ToDateTime()等:
  
  int ival = Convert::ToInt( myBonus );
  
  兩種轉換方法采用的策略有所不同顯式轉型會直接對小數部分進行截斷而Convert的成員函數則采用的是捨入算法例如上面的例子中ival賦值後的結果為而ival賦值後的結果為
  
  我們還可以直接使用字面常量(literal)來調用其對應類型的成員函數雖然這乍看起來有些怪異例如我們可以編寫如下代碼
  
  Console::Write( {} : ( )ToString() );
  
  其中( )ToString()返回的是字面常量整數的字符串表示注意外面的圓括號是必須的因為它會使得編譯器將後面的成員選擇操作符點號綁定到整數而不是將解析為一個double類型的字面常量——那樣的話後面的ToString()將變得不合法為什麼我們有時候需要這樣做呢?一種可能的情況是將一個字符串傳遞給Console的成員函數要比傳遞實際的數值來的更加高效
  
  對於字符以及字符串這樣的字面常量我們也可以像上面的整數一樣調用它們的成員函數但是它們的行為有一點點晦澀例如下面的代碼
  
  Console::WriteLine(( a )ToString() );
  
  將在控制台上打印出而非a這個字符要將字符a打印出來我們需要將其首先轉型為System::Char
  
  Console::WriteLine(((wchar_t)a)ToString() );
  
  C++/CLI對字符串字面常量采取了特殊的處理策略從某種程度上來講字符串字面常量在C++/CLI中的類型更接近System::String而非C風格的字符串指針顯然這將對重載函數的辨析產生影響例如
  
  public ref class R {
  public:
  void foo( System::String^ ); // ()
  void foo( std::string ); // ()
  void foo( const char* ); // ()
  };
  
  void bar( R^ r )
  {
  // 調用哪一個foo呢?
  r>foo( Pooh );
  }
  
  在ISOC++中這將被辨析為第個foo()因為字符串字面常量更接近const char*而非ISOC++標准庫中的string類型但是在C++/CLI中上面的調用將被辨析為第個foo()因為現在字符串字面常量被認為更接近System::String而非字符指針要理解其中的緣由讓我們往後退兩步先來看看ISOC++和C++/CLI如何辨析一個重載函數然後再來看ISOC++和C++/CLI如何辨析一個字符串字面常量
  
  一個重載函數的辨析過程通常包含以下三個步驟
  
  .選擇候選函數集合候選函數是指那些從詞法范疇來看與所調用函數名相匹配的函數例如由於我們上面是在R的一個實例上調用foo()所以所有名稱為foo但卻不是R或者其基類的成員的那些函數將不被認為是候選函數這樣看來我們現在有三個候選函數即R中三個名稱為foo的成員函數如果這個階段得到的候選函數集合為空那麼調用將告失敗
  
  .從候選函數集合中選擇可用函數集合可用函數是指函數聲明時的參數個數和它們的類型與調用時所指定的相匹配的那些函數在我們上面的例子中三個候選函數都是可用函數如果這個階段得到的可用函數集合為空那麼調用也將失敗
  
  .從可用函數集合中選擇最匹配的函數這個階段將會對實際傳遞的參數和可用函數所聲明的參數之間的轉換進行一個排名對於只含一個參數的函數來說這個過程比較簡單但是對於含有多個參數的函數來說這個過程就變得相對有些復雜如果沒有一個最佳的匹配函數勝出那麼調用將告失敗也就是說各個可用函數的參數類型到實際參數類型之間的轉換被認為一樣的好換言之多個調用之間產生了混淆
  
  那麼現在擺在我們面前有兩個問題)我們實際傳遞的參數Pooh到底是什麼類型?()在判定類型轉換的優劣時采用的是什麼算法?
  
  在ISOC++中字符串字面常量Pooh的類型為const char[]——注意在字符串字面常量後面有一個隱含的截斷字符null在上面的例子中顯然不存在這樣的精確匹配因此必須應用某種形式的類型轉換這樣兩個ISOC++候選函數()和()將進行競爭
  
  void foo( std::string ); // ()
  void foo( const char* ); // ()
  
  那麼編譯器如何從中判斷可用函數呢?C++語言對類型轉換按照優先順序定義有一個層級結構在這個結構中如果一種轉換優於另一種轉換那麼它將被排在前面在C++/CLI中我們將CLI類型的行為也集成到了ISOC++的標准類型轉換層級結構中下面是對集成之後的層級結構的一個描述
  
  )精確匹配是最好的需要注意的是精確匹配並不意味著實際傳遞的參數類型和函數聲明的形式參數類型完全匹配它們只需要足夠接近就可以了我們下面將會看到足夠接近對於ISOC++和C++/CLI中的字符串字面常量有著一些不同的含義
  
  )在標准轉換中拓寬轉換要優於非拓寬轉換例如將short拓寬為int要優於將int轉換為double
  
  )標准轉換優於裝箱(boxing)轉換例如將int轉換為double優於將int裝箱為Object
  
  )裝箱轉換優於用戶自定義的隱式轉換
  
  )用戶自定義的隱式轉換優於沒有任何轉換!
  
  )否則用戶必須使用顯式的轉型符號來表示期望的轉換
  
  對於上面兩個ISOC++下的候選函數將字符串字面常量轉換為一個std::string屬於上面第即隱式調用string的構造器來創建一個臨時string對象而將字符串字面常量轉換為一個const char* 屬於上面第條優於第因此參數為const char*的那個函數在這場競爭中勝出
  
  這種歸屬在第精確匹配下的trivial conversions實際上在技術的定義上是很嚴格的總共有種這樣的trivial conversions可以被歸為精確匹配即使在這種trivial conversions中為了規范語言對類型的選擇它們也有一個優先級的排序
  
  大多數讀者和程序員可能對於這樣的細節沒有多大興趣並且通常情況下我們也無須深入到這些細節的地方但是如果我們要得到一個直觀的語言行為並且確保它們在不同的實現上表現相同這些規則的存在就很有必要這是因為作為一門編程語言它的行為一般要具有某種程度的類型感知能力從而允許程序員忽略這些細節 下面讓我們來對這種trivial conversions做一簡單的了解其中種被稱為左值轉換(lvalue transformation)左值(lvalue)是一個可尋址的可被執行寫操作的程序實體種為限定性轉換(qualification conversion)例如在一個類型聲明上加一個const修飾符就屬於這種轉換其中種左值轉換優於限定性轉換
  
  在我們上面的例子中由本地數組到指針的轉換即由const char []到const char *就是一種左值轉換在大多數情況下我們甚至不將這看作一種轉換
  
  這種形式的左值轉換在C++/CLI中仍然適用但是在我們將System::String類引入之後字符串字面常量到const char*的轉換就不再是最好的匹配了實際上在C++/CLI中Pooh這樣的字符串字面常量的類型既是const char[
From:http://tw.wingwit.com/Article/program/ASP/201311/21784.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.