C++/CLI 概觀 王建興 qing@cs.nthu.edu.tw (Email/MSN) 2007/1/25
About Qing <ul><li>Education </li></ul><ul><ul><li>Ph.D. Candidate, Department of Computer Science, National Tsing-Hua Uni...
Agenda <ul><li>何謂 C++/CLI </li></ul><ul><li>C++/CLI 中的型別宣告 </li></ul><ul><li>Handle vs. Pointer </li></ul><ul><li>Determin...
在 C++/CLI 出現前, .NET 上的 C++ 程式員恐怕只有一個字可以形容 悶
.NET 上的 C++ 程式員為什麼悶? (1/2) <ul><li>僅管有了 Managed Extension for C++ ,但卻存在一些對程式員的困擾 </li></ul><ul><li>不夠流暢優雅的語法 </li></ul><ul...
.NET 上的 C++ 程式員為什麼悶? (2/2) <ul><li>有兩種形式的指標: unmanaged  指標及 managed 指標,其用法及表示容易造成混淆 </li></ul><ul><li>無法產生 verifiable 的程式碼...
為什麼不學 C# 就好了? <ul><li>多學一個程式語言 </li></ul><ul><li>C++ 最佳化能力較強 </li></ul><ul><li>C++ 具備 deterministic destruction (即使編譯為 MSI...
好消息是… .Net 上的 C++ 程式員不用再悶了
C++/CLI 所帶來的拯救 <ul><li>優雅流暢的語法 </li></ul><ul><li>對 CLI 的直接支援 </li></ul><ul><ul><li>property ,泛型,垃圾回收等機制全都有了直接的支援 </li></ul...
何謂 C++/CLI ? <ul><li>C++ 所支援的靜態物件模型,目標放在對執行檔速度及大小的最佳化上 </li></ul><ul><li>CLI 則為一支援動態元件編程模型的多階架構 </li></ul><ul><li>C++/CLI ...
C++/CLI 就是 C++ X CLI <ul><li>確定性的記憶體管理 </li></ul><ul><li>Template </li></ul><ul><li>Native types </li></ul><ul><li>STL 、 g...
C++/CLI 的目標就是 無接縫式的整合 Unmanaged 及 Managed Code
C++ 及 CLI 物件模型的比較 <ul><li>物件儲存空間類型多樣化 </li></ul><ul><ul><li>static, stack,  以及 heap </li></ul></ul><ul><li>物件的生命期類型多樣化 </l...
C++/CLI 中的型別宣告 <ul><li>在 C++/CLI 中可宣告下述型別 </li></ul>CLR 的 enumeration type enum class E {…} CLR 的 interface type interface...
C++ 與 CTS 型別的對應 N/A Boolean bool N/A Double long double N/A Double double N/A Single float UInt64 Int64 __int64 UInt32 Int...
各型別的用途 <ul><li>原生型別 </li></ul><ul><ul><li>具備 native code 的語義及優點 </li></ul></ul><ul><ul><li>即使被編譯成 MSIL 亦如此 </li></ul></ul>...
例:在 C++/CLI 中宣告 Reference Type <ul><li>ref  class Qing </li></ul><ul><li>{ </li></ul><ul><li>public: </li></ul><ul><li>voi...
Handle vs. Pointer <ul><li>C++/CLI 中將 native C++ 型別及 CLI 型別區分開來 </li></ul><ul><li>C++/CLI 中同樣具備指向 CLI 型別的 ” 指標”,但採用了不同的符號來...
透過 Handle 建構並運用 CLI 型別 <ul><li>Qing  ^ qing =  gcnew  Qing(); </li></ul><ul><li>qing->sayHello(); </li></ul>
使用 Pointer 和 Handle 的差異 <ul><li>Pointer 用來在 native heap 中配置空間 </li></ul><ul><ul><li>語法: T* t = new T; </li></ul></ul><ul><...
不同的兩種物件生成及運用模式 *Kate Gregory, “Moving C++ Applications to the Common Language Runtime”     Use Native Heap    Use Man...
於 Native/CLI 型別中混用 Pointer/Handle (1/2) <ul><li>在 CLI 型別中使用 Handle </li></ul><ul><li>在 CLI 型別中使用 Pointer </li></ul>ref cla...
於 Native/CLI 型別中混用 Pointer/Handle (2/2) <ul><li>在 Native 型別中使用 Handle </li></ul><ul><li>gcroot<T> 是用來包裝 System.Runtime.Int...
Tracking Reference Operator % <ul><li>& 之於 pointer ,相當於 % 之於 handle </li></ul>R1 ^pr1 = gcnew R1(); R1 %r1 =  * pr1; Conso...
Tracking Reference 的效應 array<String^>^ arr = gcnew array<String^>(3); int i = 0; for each(String^% s in arr) s = gcnew Str...
CLI 的 Non-Deterministic Finalization <ul><li>CLI 的垃圾回收機制,會在記憶體傾向不足時,將不再使用被物件佔用的記憶體空間回收再用 </li></ul><ul><li>當物件佔用的記憶體空間確定被回...
Disposal <ul><li>對於記憶體資源而言,  non-deterministic finalization 不成問題 </li></ul><ul><li>但對非記憶體資料(例如資料庫 、 檔案), 面對 non-determinis...
Deterministic Destruction <ul><li>C++/CLI 除了 CLI 上原先就有的 finalizer 之外,還提供了 destructor. </li></ul>ref class R1 { public: R1(...
Finalizer vs. Destructor <ul><li>C++/CLI 中的 Destructor 最終會被編譯成為 Dispose() ,如果用 C# 的相對應程式碼來看的話,會像是: </li></ul><ul><li>GC::S...
Why  SuppressFinalize?   public class FileStream : Stream { public override void Close() { // Clean up this object: flush ...
自動進行的 Disposal { SqlConnection conn(connString); } constructor 會被呼叫 destructor 會被自動呼叫 {   SqlConnection ^pConn = gcnew Sql...
C++/CLI 中的陣列 <ul><li>使用 Managed Heap 的 Managed Array ,其基礎型別皆為 </li></ul><ul><li>System::Array </li></ul><ul><li>使用 C++/CLI...
陣列定義語法 <ul><li>一維陣列語法 </li></ul><ul><li>多維度陣列語法 </li></ul>array<String ^> ^ strArray = gcnew array<String ^>(10); for(int ...
陣列的初始化 array<String^>^ strarr = gcnew array<String^> {“String1&quot;, “String2&quot;}; array<String^>^ strarr2 = {“String1...
參數陣列 <ul><li>C++/CLI 支援參數陣列,參數陣列必須是最後一個參數 </li></ul><ul><ul><li>用…來標示參數陣列 </li></ul></ul>void testParamArray(String ^s,  ....
Property 的語法 ref class UserAccount { public: property String^ ID { String^ get(){return id;} virtual void set(String^ valu...
Index Property 的語法 ref class OnlineUserList{ public: property UserAccount^  User[int]  { UserAccount^ get(int idx){return ...
Refernece Type 允許單一繼承多重實作 ref class R abstract {};  public ref class R2 : R, IClone, IComparable, IDisposable, IEnumerable...
Exception Handling try { throw gcnew Exception(&quot;qing&quot;); } catch(System::Exception^ e) { Console::WriteLine(e->St...
CLR 編譯模式:共有四種可供選擇 <ul><li>Mix( /clr) </li></ul><ul><ul><li>包含 managed/unmanaged code </li></ul></ul><ul><li>Pure( /clr:pur...
在 VS 2005 中選擇編譯模式
編譯模式之間的關連性 Native CLR Code Data Machine Code CLR Data / Types Native Data / Types MSIL Code Mixed C++ /clr Native C++ Veri...
CLR 編譯模式帶來的應用 <ul><li>在 C++ 應用程式中直接使用 BCL 或以 .NET 寫成的 library </li></ul><ul><ul><li>大幅提高生產力 </li></ul></ul><ul><li>將 nativ...
決定 Managed/Unmanaged 的交界處 C++ managed C++ CRT, STL, etc One call to foo() Hundreds of calls C# or C++ managed C++ CRT, STL...
C++/CLI 支援 Template template<typename T1, typename T2> class NativeData { public: NativeData(T1 t1) { m_t1 = t1; } void Do...
Tempalte 採用 Lazy Constraint (1/2) template<typename T> class Native { public: void Start(int x) { T* t = new T(); t->Bark(...
Tempalte 採用 Lazy Constraint (2/2) Native<NativeDog> d1; d1.Start(100); Native<NativePig> d2; d2.Start(100); 引發編譯器錯誤: error...
C++/CLI 支援 Generics generic<typename T1, typename T2> ref class GenericData { public: GenericData(T1 t1) { m_t1 = t1; } vo...
Generics 採用 Subtype Constraints (1/3) generic<typename T>  where T:IDog  ref class GenRef  { public: void Start(int x) { T...
Generics 採用 Subtype Constraints (2/3) ref class ClrDog : IDog { public: virtual void Bark(int Loudness) { Console::WriteLi...
Generics 採用 Subtype Constraints (3/3) GenRef<ClrDog^> g1; g1.Start(100); *http://www.codeproject.com/managedcpp/cppcligene...
使用 Reference Types 於 Template template<typename T> class CLR { public: void Start(int x) { T^ t = gcnew T(); t->Bark(x); t...
將 Template 宣告為 Reference Type template<typename T>  ref  class CLR2 { public: void Start(int x) { T^ t = gcnew T(); t->Bar...
Generics Functions generic<typename T> where T:IDog void DoAll(T t) { t->Bark(0); t->WagTail(); } *http://www.codeproject....
Template vs. Generics <ul><li>Templates are instantiated at  compile-time  with the source code.  </li></ul><ul><li>The ty...
Verifiable C++ <ul><li>以 /clr:safe 編譯,將會試著產生 verifiable assembly </li></ul><ul><li>若使用了不安全的語法時,將會得到錯誤訊息 </li></ul><ul><ul>...
使用程式庫 <ul><li>使用 managed assembly : #using </li></ul><ul><ul><li>#using <System.Data.dll> </li></ul></ul><ul><li>使用 COM 元件...
C++/CLI 的標準化現況 <ul><li>C++/CLI 在 2005 年 12 月已經成為國際標準( ECMA 372 ) </li></ul>
Reference <ul><li>Hello C++/CLI </li></ul><ul><ul><li>http://msdn.microsoft.com/msdnmag/issues/06/00/PureC/default.aspx </...
Thanks
Upcoming SlideShare
Loading in …5
×

Introduction to C++ over CLI

2,244 views

Published on

本講題將對C++/CLI做一個概觀性的介紹。
在C++/CLI之前,.NET平台上的C++開發方案,多半只能選擇採用Managed C++。無可諱言的,Managed C++本身存在一些改善的空間,諸如:語法的優雅與寫作的流暢、對泛型程式設計的支援等等。然而,在著名的C++語言大師Stan Lippman及Herb Shtter加入VC++的團隊中時,重新制定後的C++/CLI卻讓這些問題得到了解決的方案。在Visual Studio 2005中,完全支援C++標準的C++/CLI加入了新語法及語義,針對.NET環境提供了最直接的支援。
有了C++/CLI,原先標準的C++能力不僅不會受損,而C++/CLI中的標準擴充,也使得C++在.NET平台上獲得額外的加持。C++/CLI有了.NET的加持,一舉具備了reflection及垃圾回收的能力。.NET所提供的標準類別庫,也都可為其所用。再加上C++/CLI混合了unmanaged及managed兩種執行環境,更使得C++/CLI具備更多效率的空間,同時能夠開發系統層級的應用程式。
有了C++/CLI,在.NET平台上的C++程式員如同取得一把新的寶劍。

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,244
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
45
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Introduction to C++ over CLI

  1. 1. C++/CLI 概觀 王建興 qing@cs.nthu.edu.tw (Email/MSN) 2007/1/25
  2. 2. About Qing <ul><li>Education </li></ul><ul><ul><li>Ph.D. Candidate, Department of Computer Science, National Tsing-Hua University, Taiwan </li></ul></ul><ul><ul><li>Research interests: distribute network management, mobile agent, VoIP, and p2p networking </li></ul></ul><ul><li>Software Development Skills </li></ul><ul><ul><li>Programming languages: 80x86 assembly, C/C++, Java, C# </li></ul></ul><ul><ul><li>J2EE development and Web programming: EJB, JSP/Servlet </li></ul></ul><ul><ul><li>Network programming: TCP/IP, socket programming </li></ul></ul><ul><ul><li>Object Oriented Design/Programming </li></ul></ul><ul><ul><li>Design Patterns and Software Architecture </li></ul></ul><ul><ul><li>Distributed Network Management System </li></ul></ul><ul><ul><li>Peer-to-Peer Networking </li></ul></ul><ul><li>Book Translation </li></ul><ul><ul><li>Thinking in Java 2nd Edition, in Traditional Chinese </li></ul></ul><ul><ul><li>Essential C++, in Traditional Chinese </li></ul></ul>
  3. 3. Agenda <ul><li>何謂 C++/CLI </li></ul><ul><li>C++/CLI 中的型別宣告 </li></ul><ul><li>Handle vs. Pointer </li></ul><ul><li>Deterministic Destruction of C++/CLIS </li></ul><ul><li>C++/CLI 中的陣列 </li></ul><ul><li>C++/CLI 對 Property 的支援 </li></ul><ul><li>C++/CLI 的四種編譯模式 </li></ul><ul><li>Templates 及 Generics </li></ul><ul><li>C++/CLI 的標準化 </li></ul>
  4. 4. 在 C++/CLI 出現前, .NET 上的 C++ 程式員恐怕只有一個字可以形容 悶
  5. 5. .NET 上的 C++ 程式員為什麼悶? (1/2) <ul><li>僅管有了 Managed Extension for C++ ,但卻存在一些對程式員的困擾 </li></ul><ul><li>不夠流暢優雅的語法 </li></ul><ul><ul><li>例如:雙底線的關鍵字們 </li></ul></ul><ul><li>對 CLI 的支援不夠支接 </li></ul><ul><ul><li>例如:缺乏 for-each 語法,不支援 property </li></ul></ul><ul><li>C++ 與 .NET 之間的整合不夠好 </li></ul><ul><ul><li>例如:無法在 CLI 型別上使用 template ,也無法在 C++ 型別上運用 CLI 的機制,例如垃圾回收 </li></ul></ul>*http://www.codeproject.com/managedcpp/cppcliintro01.asp
  6. 6. .NET 上的 C++ 程式員為什麼悶? (2/2) <ul><li>有兩種形式的指標: unmanaged 指標及 managed 指標,其用法及表示容易造成混淆 </li></ul><ul><li>無法產生 verifiable 的程式碼 </li></ul>
  7. 7. 為什麼不學 C# 就好了? <ul><li>多學一個程式語言 </li></ul><ul><li>C++ 最佳化能力較強 </li></ul><ul><li>C++ 具備 deterministic destruction (即使編譯為 MSIL ) </li></ul><ul><li>C++ 程式員在 C++ 的特性支持下,生產力較高 </li></ul><ul><ul><li>STL </li></ul></ul><ul><ul><li>template specialization </li></ul></ul>
  8. 8. 好消息是… .Net 上的 C++ 程式員不用再悶了
  9. 9. C++/CLI 所帶來的拯救 <ul><li>優雅流暢的語法 </li></ul><ul><li>對 CLI 的直接支援 </li></ul><ul><ul><li>property ,泛型,垃圾回收等機制全都有了直接的支援 </li></ul></ul><ul><ul><li>在 unmanaged classes 上這些機制也都適用 </li></ul></ul><ul><li>妥善的橋接 .NET 與 C++ </li></ul><ul><li>透過 C++/CLI 編譯出來的程式碼,是 fully verifiable </li></ul>*http://www.codeproject.com/managedcpp/cppcliintro01.asp
  10. 10. 何謂 C++/CLI ? <ul><li>C++ 所支援的靜態物件模型,目標放在對執行檔速度及大小的最佳化上 </li></ul><ul><li>CLI 則為一支援動態元件編程模型的多階架構 </li></ul><ul><li>C++/CLI 中的” /” ,代表 C++ 與 CLI 之間的 binding </li></ul><ul><li>何謂 C++/CLI </li></ul><ul><ul><li>近似說法 1 : C++/CLI 將 C++ 靜態的物件模型繫結 (bind) 至 CLI 的動態元件模型 </li></ul></ul><ul><ul><li>近似說法 2 : C++/CLI 將 .NET 編程模型整合進到 C++ 中 </li></ul></ul>* Stanley B. Lippman , http://msdn.microsoft.com/msdnmag/issues/06/00/PureC/default.aspx
  11. 11. C++/CLI 就是 C++ X CLI <ul><li>確定性的記憶體管理 </li></ul><ul><li>Template </li></ul><ul><li>Native types </li></ul><ul><li>STL 、 generic algorithms </li></ul><ul><li>指標 </li></ul><ul><li>複製建構及指派 </li></ul><ul><li>垃圾收集, finalizer </li></ul><ul><li>泛型 </li></ul><ul><li>Reference 及 value types </li></ul><ul><li>Interface </li></ul><ul><li>Verifiability </li></ul><ul><li>Security </li></ul><ul><li>Properties, delegates, events </li></ul><ul><li>功能強力的 BCL </li></ul>C++ 的特點 CLI 的特點 C++/CLI 發揮 C++ 及 CLI 的相乘效果
  12. 12. C++/CLI 的目標就是 無接縫式的整合 Unmanaged 及 Managed Code
  13. 13. C++ 及 CLI 物件模型的比較 <ul><li>物件儲存空間類型多樣化 </li></ul><ul><ul><li>static, stack, 以及 heap </li></ul></ul><ul><li>物件的生命期類型多樣化 </li></ul><ul><ul><li>static object 有著和程式相同的生命期 </li></ul></ul><ul><ul><li>stack 上的 object ,則在和 scope({ … }) 的生命期相同 </li></ul></ul><ul><ul><li>heap 上的 object ,則由程式員自行操控其生命期 </li></ul></ul><ul><li>物件建構及指派的深層拷貝模型 </li></ul><ul><li>編譯時,原始碼中必須含括所有動用型別的資訊 </li></ul><ul><li>物件儲存空間類型單純 </li></ul><ul><ul><li>Value type 儲存於 stack </li></ul></ul><ul><ul><li>Reference type 儲存於 managed heap 上 </li></ul></ul><ul><li>物件的生命期具不確定性 </li></ul><ul><ul><li>Reference types 須倚靠垃圾收集器回收 </li></ul></ul><ul><li>物件的指派採淺層參考語義 </li></ul><ul><li>編譯時,型別資訊由所使用型別的 metadata 提供 </li></ul>C++ 的靜態物件模型 CLI 的動態物件模型
  14. 14. C++/CLI 中的型別宣告 <ul><li>在 C++/CLI 中可宣告下述型別 </li></ul>CLR 的 enumeration type enum class E {…} CLR 的 interface type interface class I {…} CLR 的 value type value class V {…} CLR 的 reference type ref class R {…} C++ 原生類別(過去 C++ 程式員所用) class N {…} 所宣告的型別 宣告語法
  15. 15. C++ 與 CTS 型別的對應 N/A Boolean bool N/A Double long double N/A Double double N/A Single float UInt64 Int64 __int64 UInt32 Int32 long int UInt32 Int32 int, __int32 UInt16 Int16 short int Byte Sbyte char CTS Unsigned Type CTS Signed Type C++ Type
  16. 16. 各型別的用途 <ul><li>原生型別 </li></ul><ul><ul><li>具備 native code 的語義及優點 </li></ul></ul><ul><ul><li>即使被編譯成 MSIL 亦如此 </li></ul></ul><ul><li>Reference Type </li></ul><ul><ul><li>可被垃圾收集器回收,提供簡便的記憶體管理模式 </li></ul></ul><ul><li>Value Type </li></ul><ul><ul><li>輕量級的型別(例如像整數之類的型別) </li></ul></ul><ul><li>Interface Type </li></ul><ul><ul><li>宣告 CLR 中的介面型別 </li></ul></ul><ul><li>Enumeration Type </li></ul><ul><ul><li>宣告 CLR 中的列舉型別 </li></ul></ul>
  17. 17. 例:在 C++/CLI 中宣告 Reference Type <ul><li>ref class Qing </li></ul><ul><li>{ </li></ul><ul><li>public: </li></ul><ul><li>void sayHello(); </li></ul><ul><li>}; </li></ul><ul><li>void Qing::sayHello() </li></ul><ul><li>{ </li></ul><ul><li>Console::WriteLine(&quot;Hello!&quot;); </li></ul><ul><li>} </li></ul>多半宣告在 .h 檔裡 多半宣告在 .pp 檔裡
  18. 18. Handle vs. Pointer <ul><li>C++/CLI 中將 native C++ 型別及 CLI 型別區分開來 </li></ul><ul><li>C++/CLI 中同樣具備指向 CLI 型別的 ” 指標”,但採用了不同的符號來表示,同時賦予一個不同的名稱,以資區別 </li></ul><ul><ul><li>這個名稱就是 Handle (相對於 Pointer ) </li></ul></ul><ul><ul><li>這個符號就是 ^ (相對於 * ) </li></ul></ul><ul><li>建構 native C++ 型別及 CLI 型別的關鍵字也已有所區隔 </li></ul><ul><ul><li>new :產生 native C++ 型別 </li></ul></ul><ul><ul><li>gcnew :產生 CLI 型別( gc 意指 garbage collected ,垃圾回收之意) </li></ul></ul>
  19. 19. 透過 Handle 建構並運用 CLI 型別 <ul><li>Qing ^ qing = gcnew Qing(); </li></ul><ul><li>qing->sayHello(); </li></ul>
  20. 20. 使用 Pointer 和 Handle 的差異 <ul><li>Pointer 用來在 native heap 中配置空間 </li></ul><ul><ul><li>語法: T* t = new T; </li></ul></ul><ul><ul><li>指標指向的位置是穩定的(不受 GC 影響),甚至可以被轉型為 int </li></ul></ul><ul><ul><li>倘若未自行釋放記憶體( delete ),則會產生 memory leak </li></ul></ul><ul><li>Handle 用來在 managed heap 中配置空間 </li></ul><ul><ul><li>語法: T^ t = gcnew T; </li></ul></ul><ul><ul><li>GC 會自動釋放位於 managed heap 中的物件所佔用的空間 </li></ul></ul><ul><ul><li>但程式員仍可針對 managed heap 上的物件呼叫 delete </li></ul></ul>
  21. 21. 不同的兩種物件生成及運用模式 *Kate Gregory, “Moving C++ Applications to the Common Language Runtime”   Use Native Heap    Use Managed Heap   Use Stack ^ and % always * and & never Verifiability d elete delete Free gcnew new Allocate % & Reference ^ * Pointer / Handle Managed Native
  22. 22. 於 Native/CLI 型別中混用 Pointer/Handle (1/2) <ul><li>在 CLI 型別中使用 Handle </li></ul><ul><li>在 CLI 型別中使用 Pointer </li></ul>ref class R { private: String ^str; } ref class R { private: std::string* str; }
  23. 23. 於 Native/CLI 型別中混用 Pointer/Handle (2/2) <ul><li>在 Native 型別中使用 Handle </li></ul><ul><li>gcroot<T> 是用來包裝 System.Runtime.InteropServices.GCHandle 的一個 template class </li></ul>*http://www.codeproject.com/managedcpp/ijw_unmanaged.asp class N { private: gcroot<String^> str;; }
  24. 24. Tracking Reference Operator % <ul><li>& 之於 pointer ,相當於 % 之於 handle </li></ul>R1 ^pr1 = gcnew R1(); R1 %r1 = * pr1; Console::WriteLine(r1 . ToString()); 不再是 -> 同樣使用 *
  25. 25. Tracking Reference 的效應 array<String^>^ arr = gcnew array<String^>(3); int i = 0; for each(String^% s in arr) s = gcnew String(i++.ToString()); for each(String^ s in arr) Console::WriteLine(s); 執行結果: 0 1 2 array<String^>^ arr = gcnew array<String^>(3); int i = 0; for each(String^ s in arr) s = gcnew String(i++.ToString()); for each(String^ s in arr) Console::WriteLine(s); 執行結果:
  26. 26. CLI 的 Non-Deterministic Finalization <ul><li>CLI 的垃圾回收機制,會在記憶體傾向不足時,將不再使用被物件佔用的記憶體空間回收再用 </li></ul><ul><li>當物件佔用的記憶體空間確定被回收前的一刻,該物件的 Finalize() 會被呼叫,此即為 finalization (終始化)動作 </li></ul><ul><li>Finalization 執行的時機及是否會被執行任誰都說不得準 </li></ul><ul><ul><li>所以被稱為 non-deterministic finalization </li></ul></ul>
  27. 27. Disposal <ul><li>對於記憶體資源而言, non-deterministic finalization 不成問題 </li></ul><ul><li>但對非記憶體資料(例如資料庫 、 檔案), 面對 non-deterministic finalization 的程式員得多費心才能使程式如預期的運作 </li></ul><ul><li>對 .NET 而言,慣例上清理此類資料的動作,會定義於名為 Close() 或 Dispose() 的方法中 </li></ul><ul><li>但這麼一來,程式員得自行呼叫 Close() 或 Dispose() 來進行清理動作 </li></ul>
  28. 28. Deterministic Destruction <ul><li>C++/CLI 除了 CLI 上原先就有的 finalizer 之外,還提供了 destructor. </li></ul>ref class R1 { public: R1() {} ~R1() {} protected: !R1() {} }; constructor destructor finalizer * 注意: C++/CLI 使用了 C# 中用來表示 Finalizer 的符號來表示 Destructor
  29. 29. Finalizer vs. Destructor <ul><li>C++/CLI 中的 Destructor 最終會被編譯成為 Dispose() ,如果用 C# 的相對應程式碼來看的話,會像是: </li></ul><ul><li>GC::SuppressFinalize() 會要求系統不要呼叫物件的 finalizer() ,避免物件被清理兩次 </li></ul>public void Dispose()//IDisposable::Dispose { GC.SuppressFinalize(this); } *http://www.codeproject.com/managedcpp/cppclidtors.asp *http://msdn2.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx
  30. 30. Why SuppressFinalize? public class FileStream : Stream { public override void Close() { // Clean up this object: flush data and close file … // There is no reason to Finalize this object now GC.SuppressFinalize(this); } protected override void Finalize() { Close(); // Clean up this object: flush data and close file } // Rest of FileStream methods go here … } *http://www.codeproject.com/managedcpp/cppclidtors.asp 如果程式員自行呼叫了 Close() , 但 GC 又呼叫了 Finalize() 便會引發 Close() 被叫用兩次
  31. 31. 自動進行的 Disposal { SqlConnection conn(connString); } constructor 會被呼叫 destructor 會被自動呼叫 { SqlConnection ^pConn = gcnew SqlConnection(connString); } constructor 會被呼叫 之後就要等待 GC 動作了
  32. 32. C++/CLI 中的陣列 <ul><li>使用 Managed Heap 的 Managed Array ,其基礎型別皆為 </li></ul><ul><li>System::Array </li></ul><ul><li>使用 C++/CLI 的陣列時,可以想像存在一個虛擬的 template </li></ul>http://www.codeproject.com/managedcpp/cppcliarrays.asp namespace stdcli::language { template<typename T, int rank = 1> ref class array : System::Array {}; }
  33. 33. 陣列定義語法 <ul><li>一維陣列語法 </li></ul><ul><li>多維度陣列語法 </li></ul>array<String ^> ^ strArray = gcnew array<String ^>(10); for(int i=0;i<strArray->Length;i++) { strArray[i] = &quot;&quot;+i; Console::WriteLine(strArray[i]); } array<String ^, 3> ^ strArray = gcnew array<String ^, 3>(4, 3, 2); 維度 每個維度的長度
  34. 34. 陣列的初始化 array<String^>^ strarr = gcnew array<String^> {“String1&quot;, “String2&quot;}; array<String^>^ strarr2 = {“String1&quot;, “String2&quot;}; array<Object^,2> ^ objarr = {{“String1&quot;, 1}, {“String2&quot;, 2}};
  35. 35. 參數陣列 <ul><li>C++/CLI 支援參數陣列,參數陣列必須是最後一個參數 </li></ul><ul><ul><li>用…來標示參數陣列 </li></ul></ul>void testParamArray(String ^s, ... array<String ^>^ params) { Console::WriteLine(s+&quot;: &quot;); for(int i=0;i<params->Length;i++) Console::WriteLine(params[i]); } int main(array<System::String ^> ^args) { testParamArray(&quot;Hello&quot;, &quot;qing&quot;); testParamArray(&quot;Hello&quot;, &quot;qing&quot;, &quot;chrisma&quot;); }
  36. 36. Property 的語法 ref class UserAccount { public: property String^ ID { String^ get(){return id;} virtual void set(String^ value){id = value;} } private: String^ id; }; 就和 C# 的定義方式類似
  37. 37. Index Property 的語法 ref class OnlineUserList{ public: property UserAccount^ User[int] { UserAccount^ get(int idx){return (UserAccount^) alUser[idx];} } OnlineUserList() { alUser = gcnew System::Collections::ArrayList(); } // … private: System::Collections::ArrayList ^alUser; };
  38. 38. Refernece Type 允許單一繼承多重實作 ref class R abstract {}; public ref class R2 : R, IClone, IComparable, IDisposable, IEnumerable { }; 所有 reference type 都繼承自 System::Object 最多繼承一個類別,但可以實作多個介面
  39. 39. Exception Handling try { throw gcnew Exception(&quot;qing&quot;); } catch(System::Exception^ e) { Console::WriteLine(e->StackTrace); }
  40. 40. CLR 編譯模式:共有四種可供選擇 <ul><li>Mix( /clr) </li></ul><ul><ul><li>包含 managed/unmanaged code </li></ul></ul><ul><li>Pure( /clr:pure ) </li></ul><ul><ul><li>僅包含 managed code </li></ul></ul><ul><ul><li>但仍可使用 #include 並呼叫原生 API </li></ul></ul><ul><li>Verifiable( clr:safe) </li></ul><ul><ul><li>僅包含 verifiable code </li></ul></ul><ul><li>Managed Extensions for C++( clr:oldSyntax ) </li></ul><ul><ul><li>用來編譯舊式的程式碼 </li></ul></ul>
  41. 41. 在 VS 2005 中選擇編譯模式
  42. 42. 編譯模式之間的關連性 Native CLR Code Data Machine Code CLR Data / Types Native Data / Types MSIL Code Mixed C++ /clr Native C++ Verifiable C++ /clr:safe Pure C++ /clr:pure
  43. 43. CLR 編譯模式帶來的應用 <ul><li>在 C++ 應用程式中直接使用 BCL 或以 .NET 寫成的 library </li></ul><ul><ul><li>大幅提高生產力 </li></ul></ul><ul><li>將 native code 的功能,以 .NET 物件模型的方式對外提供 </li></ul><ul><ul><li>便於其他 .NET 應用程式使用( ASP.NET ) </li></ul></ul>
  44. 44. 決定 Managed/Unmanaged 的交界處 C++ managed C++ CRT, STL, etc One call to foo() Hundreds of calls C# or C++ managed C++ CRT, STL, etc One call to foo() Hundreds of calls C# C++ CRT, STL, etc Hundreds of calls C++ One call to foo() One call * Kate Gregory, “ Moving C++ Applications to the Common Language Runtime”
  45. 45. C++/CLI 支援 Template template<typename T1, typename T2> class NativeData { public: NativeData(T1 t1) { m_t1 = t1; } void DoStuff(T2 t2) { //... } private: T1 m_t1; }; *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  46. 46. Tempalte 採用 Lazy Constraint (1/2) template<typename T> class Native { public: void Start(int x) { T* t = new T(); t->Bark(x); t->WagTail(); delete t; } }; 如何確定 t 有 Bark() 及 WagTail() 兩 methods 呢? *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  47. 47. Tempalte 採用 Lazy Constraint (2/2) Native<NativeDog> d1; d1.Start(100); Native<NativePig> d2; d2.Start(100); 引發編譯器錯誤: error C2039: 'Bark' : is not a member of 'NativePig' *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  48. 48. C++/CLI 支援 Generics generic<typename T1, typename T2> ref class GenericData { public: GenericData(T1 t1) { m_t1 = t1; } void DoStuff(T2 t2) { //... } private: T1 m_t1; }; *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  49. 49. Generics 採用 Subtype Constraints (1/3) generic<typename T> where T:IDog ref class GenRef { public: void Start(int x) { T t = Activator::CreateInstance<T>(); t->Bark(x); t->WagTail(); delete safe_cast<Object^>(t); } }; 透過限制 T 必須實作的介面來進行約束 *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  50. 50. Generics 採用 Subtype Constraints (2/3) ref class ClrDog : IDog { public: virtual void Bark(int Loudness) { Console::WriteLine(&quot;ClrDog::Bark {0}&quot;,Loudness); } virtual void WagTail() { Console::WriteLine(&quot;ClrDog::WagTail&quot;); } }; *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  51. 51. Generics 採用 Subtype Constraints (3/3) GenRef<ClrDog^> g1; g1.Start(100); *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  52. 52. 使用 Reference Types 於 Template template<typename T> class CLR { public: void Start(int x) { T^ t = gcnew T(); t->Bark(x); t->WagTail(); delete t; } }; CLR<ClrDog> g2; g2.Start(100)
  53. 53. 將 Template 宣告為 Reference Type template<typename T> ref class CLR2 { public: void Start(int x) { T^ t = gcnew T(); t->Bark(x); t->WagTail(); delete t; } }; CLR 2 <ClrDog> g 3 ; g 3 .Start(100) Console::WriteLine(g3.GetType()->Name); 執行結果: ClrDog::Bark 100 ClrDog::WagTail CLR2<ClrDog>
  54. 54. Generics Functions generic<typename T> where T:IDog void DoAll(T t) { t->Bark(0); t->WagTail(); } *http://www.codeproject.com/managedcpp/cppcligenerics.asp
  55. 55. Template vs. Generics <ul><li>Templates are instantiated at compile-time with the source code. </li></ul><ul><li>The type checking of a template are performed at the point where the template is defined and instantiated . </li></ul><ul><li>Tempaltes allow specialization. </li></ul><ul><li>Templates allow non-type parameters. </li></ul><ul><li>Templates use &quot; lazy structural constraints &quot;. </li></ul><ul><li>Generics are instantiated at run-time by the CLR. </li></ul><ul><li>The type checking of a generic is peformend at the point where the generic is defined . </li></ul><ul><li>Generics are cross-language . </li></ul><ul><li>Generics do not allow specialization. </li></ul><ul><li>Generics do not allow non-type parameters. </li></ul><ul><li>Generics use subtype constraints . </li></ul>*http://blogs.msdn.com/branbray/archive/2003/11/19/51023.aspx
  56. 56. Verifiable C++ <ul><li>以 /clr:safe 編譯,將會試著產生 verifiable assembly </li></ul><ul><li>若使用了不安全的語法時,將會得到錯誤訊息 </li></ul><ul><ul><li>例如,不能使用指標運算 </li></ul></ul><ul><li>諸如 tempaltes, deterministic destruction 其他功能則是安全的 </li></ul>
  57. 57. 使用程式庫 <ul><li>使用 managed assembly : #using </li></ul><ul><ul><li>#using <System.Data.dll> </li></ul></ul><ul><li>使用 COM 元件: #import </li></ul><ul><ul><li>#using <msxml4.dll> </li></ul></ul><ul><li>使用 Standard C++ Library : #include </li></ul><ul><ul><li>#include <iostream> </li></ul></ul>
  58. 58. C++/CLI 的標準化現況 <ul><li>C++/CLI 在 2005 年 12 月已經成為國際標準( ECMA 372 ) </li></ul>
  59. 59. Reference <ul><li>Hello C++/CLI </li></ul><ul><ul><li>http://msdn.microsoft.com/msdnmag/issues/06/00/PureC/default.aspx </li></ul></ul><ul><li>ECMA-372 : C++/CLI Language Specification </li></ul><ul><ul><li>http://www.ecma-international.org/publications/standards/Ecma-372.htm </li></ul></ul><ul><li>void Nish(char *szBlog) </li></ul><ul><ul><li>http://blog.voidnish.com/index.php?cat=2 </li></ul></ul><ul><li>The Code Project </li></ul><ul><ul><li>http://www.codeproject.com/managedcpp/#C%2B%2B%2FCLI </li></ul></ul>
  60. 60. Thanks

×