C++/CLI 學習筆記
阿新 • • 發佈:2019-02-05
- 型別定義語法:
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; - 用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_Item和set_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 定義。