1. 程式人生 > >C++/CLI 學習筆記

C++/CLI 學習筆記

    • 型別定義語法:
      public ref class Block {}; // 引用型別定義public value class Vector {}; // 值型別定義public interface class IMyFile {}; // 介面定義public enum class MyEnum{}; // 列舉定義public ref class Shape abstract {};
      public
      ref class String sealed {};
      public
      ref class State abstract sealed {}; //一個類既宣告為抽象類也宣告為
      密封類。這是一種被稱為靜態類的特殊情況
    • 繼承:只支援公有方式的單繼承。public關鍵字可忽略
      ref class My : File{}; 
      ref class My : public File{};
    • 跟蹤控制代碼:引用類型別的物件用一個新的宣告性符號(^)宣告,正式的表述為跟蹤控制代碼,不正式的表述為帽子
    • new:
      Button^ button1 = gcnew Button;         // OK: 託管堆int * pi1 = new int;                                 
      // OK: 本機堆interior_ptr<Int32> pi2 = gcnew Int32; // OK: 託管堆interior_ptr通常表示一個物件的地址,這個物件可能(但不必)位於託管堆上。如果指向的物件確實位於託管堆上,那麼它在物件被重新定位時被透明地更新。
    • nullptr表示空跟蹤控制代碼,nullptr可以轉化成任何跟蹤控制代碼型別或者指標,但是不能提升為一個整數型別
    • 陣列定義:
      array<Object^>^ myArray = gcnew array<Object^>(2);
      array<String^,2>^ myMat = gcnew array<String^,2>(4,4);
      array<Object^>^ myArray = gcnew array<Object^>(4){ 1, 1, 2, 3 };
    • 物件析構:
      ~ClassName解構函式被內部重新命名為 Dispose()方法,並且引用類自動擴充套件以實現 IDisposable介面!ClassName終止器將被內部合成為 Finalize()方法,並在有基類的情況下在其末尾會插入基類的 Finalize()方法的呼叫。如果解構函式被顯式地呼叫,那麼終止器會被抑制。可以像傳統C++那樣定義一個“棧物件”,當物件離開作用域的時候會自動呼叫Dispose方法,這類似於C#的using語法
      對跟蹤控制代碼執行delete相當於顯式的Dispose呼叫。
    • 屬性和索引器:
      property double x  // 普通屬性{
        
      double get()
         {
            return _x;
         }
      private// 可以顯式指定,也可省略void set( double newx )
         {
            _x = newx;
         }
      }
      property double x; //等價的簡潔屬性語法
      property int Row [int] 
      // 普通索引器{
         int get( int r );
         void set( int r, Vector^ value );
      }
      property int default [int,int]  // 預設索引器。當指定了 default索引屬性時,下面兩個名字被保留:get_Itemset_Item。這是因為它們是 default索引屬性產生的底層名稱{
         int get( int r, int c );
         void set( int r, int c, float value );
      }
    • 代理和事件
      delegate void DblClickEventHandler( String^ ); 
      event DblClickEventHandler^ OnDblClick;  // 隱式事件宣告// 顯式事件宣告,每種子操作的可見性都是可以定製的
      f^ _E;
      event f^ E1
      {
      public:
         void
      add( f^ d )
         {
            _E += d;
         }
      protected:
         void
      remove( f^ d )
         {
            _E -= d;
         }
      private:
         void
      raise( int i )
         {
            if ( _E )
               _E( i );
         }
      }
      // 事件的掛載和解除安裝
      pE->E1 += gcnew f( pE, &E::handler );
      pE->E1
      -= gcnew f( pE, &E::handler );
    • 虛擬函式:
      virtual void f();  // 虛擬函式宣告virtual void f()=0; // 純虛擬函式宣告virtual void f() abstract;  // 純虛擬函式宣告virtual void f() sealed; // 虛擬函式的封閉
    • 支援運算子過載
      static Vector^ operator /( const Vector^, double );
    • 自定義型別轉換
      ref struct MyDouble
      {
      public:
         static
      operator MyDouble^ ( int i );
         static
      explicit operator int ( MyDouble^ val );
         static
      explicit operator String^ ( MyDouble^ val );
      };
    • 顯式介面實現
      public ref class R : public ICloneable 
      {
        
      // 通過 ICloneable 使用 ...
         Object^ InterfaceClone() = ICloneable::Clone;  // 要求為顯式重寫的介面成員賦予一個在類中唯一的名稱// 通過一個 R 物件使用 ...
         virtual R^ Clone() new;
      };
    • 虛擬函式重寫
      虛擬函式不能重寫不可訪問的基類虛擬函式,繼承的方法不必沿用同樣的訪問級別
    • static const整型將會在編譯時展開而不納入到CLR常量,可以通過literal int LOG_DEBUG = 4 語法顯式的指明為CLR常用
    • 列舉和整數之間的轉換:safe_cast<int>(myEnum),用static_cast也可以做到,但前者會產生正確性驗證的MSIL程式碼
    • 指標
      V* 可指向非託管堆和棧地址
      V^ 可指向託管堆的地址,若為值型別,則為裝箱地址
      interior_ptr<V>
      指向任何地址,若為託管堆地址,則會自動同步更新pin_ptr<V> 訂住指標,pin_ptr<V>物件超出作用域後將會解除pin
    • 變長引數
      int Add(...array<int>^ args){}
    • Type
      String::typeid == str->GetType()
    • 型別轉換
      static_cast<T>:不會檢測正確性的暴力轉換,可能返回錯誤的結果,不建議使用dynamic_cast<T>:失敗情況下會返回nullptr
      safe_cast<T>
      或者(T)C風格轉換:失敗時將丟擲InvalidCastException異常

和大量C++程式碼互動可能會出現"error LNK2028: 無法解析的標記……__clrcall……"的連結錯誤,可以使用“/clr”選項,而不是預設的“/clr:pure”。也可以採用#pragma managed指令將非託管標頭檔案包起來:

#pragma managed(push, off)

#include <***.h>

#include <***.h>

#pragma managed(pop)

參考:


2011-5-20

auto_handle Automatic resource management which can be used to embed a virtual handle into a managed type.

auto_gcroot Automatic resource management (like auto_ptr Class) which can be used to embed a virtual handle into a native type.


2012-2-14

若採用了C++/CLI,則會有巨集 __cplusplus_cli 定義。