http://blog.csdn.net/my_business/article/details/7497248什麼是C++ /CX? 首先要明白它跟C++ 0x/11以及C++ /CLR是完全不同的東西。C++ 0x/11是目前最新的C++標準庫,而C++ /CX其實是微軟在Win8開發平台下,對C++語言的一種擴充。C++ /CLR是微軟為了C++能在.Net下運行,針對CLR,雖然也是對C++的擴充,但它編譯後是託管於CLR的,屬於Managed C++。而C++ /CX則屬於Native C++,它不使用CLR也沒有記憶體回收機制。雖然C++ /CX有些新文法特性是直接從/CLR借鑒過來的,但是從底層實現上來看,它們是完全不同的兩種擴充。本文會簡單介紹C++ /CX在文法上的一些擴充。
1.實值型別value和參考型別ref
value和ref都是用來定義class的,所以有如下的文法:
[cpp] view plaincopy
- ref class Object{};
- value class Object{};
兩者有什麼不同?其實參考型別ref類似於Java裡面的引用概念,而實值型別value就是我們通常理解的C++類型。那又為什麼要增加這樣的關鍵字來進行區分呢?原因是不管統一成ref類型還是value類型都有一定缺陷。
值
類型value的話,在棧上分配空間,效率較高,但是它不支援多態,所以比如作為函數傳回值使用時,有時會存在部分拷貝的問題。其實標準C++裡面都是值
類型value,別說有指標什麼呢,指標本身不過是個整型的地址值,它還是實值型別的,也別跟我說什麼函數參數傳遞有傳值和傳址呢,即使傳址,所傳遞的指標
本身還是以值的形式傳遞的。
而參考型別ref,支援多態,但是它是在堆上分配空間,效率較低,而且會帶來額外引用計數上的開銷。
所以C++ /CX決定把兩者區分開來,讓開發人員根據實際情況是選擇。比如沒必要支援多態的我們可以考慮使用value類型,比如希望交給系統管理引用計數的我們可以考慮使用ref類型。
2. public類C++ /CX裡有這樣的定義: [cpp] view plaincopy
- public ref class Object {};
- public value class Object {};
用public來定義類,作用其實顯而易見,所有準備對外公開的類必須設為
public,比如組件裡對外公布的類,如果不定義為public的話,外部是訪問不到指定類型的。另外Native
C++類(標準C++裡的類)不能被定義為public,只有ref和value類型的類才可以設定為public,所以下面的代碼編譯會報錯:[cpp] view plaincopy
- public class Object {}; // compiler error
另外還歸納出以下2點:
1. 標準C++方式的類不能被使用在public類的public屬性成員中。
2. public ref類型類的public屬性成員中,除非使用property,否則不能聲明類成員變數。
3. public value類型的類的public屬性成員中,不能聲明類成員變數以外的成員,如函數等。
3. ^符號C++ /CX中,就是用^來表示當前資料類型是ref參考型別。比如有如下class:
[cpp] view plaincopy
- ref class SomeObj {
- public:
- void SomeFunc();
- };
那麼在建立這個類對象時,由於是ref參考型別,所以會通過如下方式建立對象:[cpp] view plaincopy
- SomeObj^ obj = ref new SomeObj();
訪問類具體成員對象時使用“->”
[cpp] view plaincopy
- obj->SomeFunc();
^的變數代表它是參考型別的,系統會負責他們的引用計數,當引用計數為0時,它們會被銷毀。
4. property可以在public屬性中用property關鍵字來公開類的成員變數,比如:
[cpp] view plaincopy
- ref class SomeObj {
- public:
- property int propertyX;
- };
可能你會覺得上面的寫法跟不加property貌似沒有什麼區別,在使用確實上是一樣的,但是用property的方式其實是會去自動產生針對m_propX的預設get(),set()函數,類似下面這樣: [cpp] view plaincopy
- ref class SomeObj {
- public:
- property int propertyX{
- int get() { return mX; }
- void set(int x) { mX = x; };
- }
- private:
- int mX;
- };
那property關鍵字的使用到底有什麼實際意義呢?首先,如果是public定義的類,那麼它的public屬性中只能通過property才能定義成員變數,如下這樣的定義編譯會出錯: [cpp] view plaincopy
- public ref class SomeObj {
- public:
- int mX; // compiler error
- };
其次,通過property可以控製成員變數的存取權限,比如唯讀,可讀可寫等,如下代碼就把propertyX設定為唯讀了: [cpp] view plaincopy
- ref class SomeObj {
- public:
- property int propertyX{
- int get() { return mX; }
- }
- private:
- int mX;
- };
同時我們還可以自己定義成員變數的讀操作或寫操作,如下代碼把寫操作控製為只會被設定為非0的值: [cpp] view plaincopy
- ref class SomeObj {
- public:
- property int propertyX{
- int get() { return mX; }
- void set(int x) {
- if (x != 0) mX = x;
- };
- }
- private:
- int mX;
- };
5. 委託delegate和事件event先看delegate的一個執行個體:
[cpp] view plaincopy
- delegate void EventHandler(int x);
- ref class WinRTObj sealed
- {
- public:
- WinRTObj() {
- eHandler = ref new EventHandler([this](int x) {
- this->mX = x;
- });
- }
- void FireEvent(int x) {
- eHandler(x);
- }
- EventHandler^ eHandler;
- private:
- int mX;
- };
delegate聲明的EventHandler其實功能就類似於函數指標,在WinRTObj類中我們定義了EventHandler^類型的成員變數,並在建構函式中初始化,new EventHandler時的參數是一個Lambda運算式的匿名函數,所以在FireEvent中調用eHandler(x)時,其實就會去運行這個匿名函數。
我們再把event應用到上面這個例子中,看看event有什麼功能: [cpp] view plaincopy
- delegate void EventHandler(int x);
- ref class WinRTObj sealed
- {
- public:
- WinRTObj() {
- eHandler += ref new EventHandler([this](int x) {
- this->mX = x;
- });
- }
- void FireEvent(int x) {
- eHandler(x);
- }
- event EventHandler^ eHandler;
- private:
- int mX;
- };
上面的代碼我們只是在聲明eHandler時用了event關鍵字,同時在建構函式建立eHandler時,把"="改成了"+="。那麼event增加了什麼特性呢?從"+="可以看出,我們可以通過"+="向eHandler添加多個委託,如下所示: [cpp] view plaincopy
- WinRTObj() {
- eHandler += ref new EventHandler([this](int x) {
- this->mX = x;
- });
- eHandler += ref new EventHandler([this](int x) {
- // ......
- });
- eHandler::add(ref new EventHandler([this](int x) {
- // ......
- }));
- auto temp = eHandler::add(ref new EventHandler([this](int x) {
-
- // ......
- }));
- eHandler::remove(temp);
- }
從上面的代碼可以看出,除了用"+="來添加委託外,我們還可以用add方法,同時也可以用remove方法刪除已經綁定的委託。現在大家應該明白delegate結合event的具體作用了吧。
6. partial類partial關鍵字也是用來修飾class,它可以讓類可以再多個地方定義同一個類,在編譯的時候會自動合并。比如: [cpp] view plaincopy
- partial ref class N
- {
- public:
- int Method1();
- static int sData1;
- };
- ref class N
- {
- public:
- void Method2();
- int mData2;
- };
有什麼用呢?其實在實際開發的代碼中應該很少會用到,之所以需要partial,
是因為Metro
UI的介面是用XAML畫的,VS會把XAML傳變為實際代碼,因為這些UI代碼跟本身開發的UI邏輯代碼等是屬於同一個類,所以XAML轉變的那部分會
被定義為partial,然後編譯的時候會被自動合并。
好了,關於C++ /CX的特性就說這麼多,其實這些以外/CX還有很多新特性,比如內建類型,C++模板,枚舉,異常等方面都有一些新的擴充。還是那句話,本文只是個說明的引子,更全的資料參照MSDN吧。