程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> C++:最強大的.NET語言之可訪問性

C++:最強大的.NET語言之可訪問性

編輯:vc教程
  CLR定義了一些用於訪問存取的修飾成分,其作用超越了本地C++中類成員函數與變量的對等物(如:public、private、protected),不僅如此,甚至還能定義命名空間或嵌套類型的可訪問性。為了讓C++/CLI達到作為低級語言的目標,除訪問性之外,它還提供了比其他CLR平台高級語言更多的控制。

  本地C++可訪問性與CLR中定義的可訪問性相比,其最大不同之處在於:本地C++訪問指示符通常用於限制同一程序中從其他代碼訪問類成員;而CLR定義的類型和成員的可訪問性,不只是針對同一程序集中的其他代碼,還針對從其他程序集中引用它的代碼。

  一個命名空間,或非嵌套類型,如class或delegate類型,可在類型定義之前,通過加上public或private關鍵字來指定程序集之外的可見度。

public ref class ReferenceType {};
   如果顯式地指定了可見度,對程序集來說,類型會被假定為私有類型(private)。

  類成員的訪問指示符同樣也被擴展,以允許一起使用兩個關鍵字來指定來自內部和外部的訪問。在這兩個關鍵字中,限制更多的一者定義了來自程序集外的訪問性,而另外一個則定義了程序集內的訪問性。如果只用了一個關鍵字,那它將同時作用於內部與外部的訪問性。這種設計思想對定義類型與類成員的可訪問性提供了巨大的彈性,以下是示例:

public ref class ReferenceType
{
public:
//程序集內部與外部均可見
private public:
//只對程序集內部可見
protected public:
//對程序集內所有代碼可見;對外部繼承類型可見
};
  屬性

  除嵌套類型之外,CLR類型只能包含方法與字段。為了讓程序員更清楚地表達代碼內涵,可使用元數據來指明某特定的方法將被編程語言當作屬性。嚴格來說,一個CLR屬性是它的包含類的一個成員,然而,屬性沒有分配的存儲空間,它只是實現屬性的各自方法的一個命名引用,而不同的編譯器,碰到源代碼中有關屬性的語法時,將會生成各自所需的元數據。這就是說,類型的使用者,可在它們的語言中使用屬性語法,來訪問實現屬性的get和set方法。與本地C++相比,C#對屬性支持最好。

public string Name
{
get
{
return m_name;
}
set
{
m_name = value;
}
}
  C#編譯器會生成對應的get_Name與set_Name方法,並且也會包含必要的元數據以指明其聯系。在托管C++中,引入了關鍵字__property來指明一個在語義上實現屬性的方法。

__property String* get_Name()
{
return m_value;
}
__property String* set_Name(String* value)
{
m_value = value;
}
  很明顯,這不是理想的情況,不但需要使用這個"難看"的__property關鍵字,而且此處沒有任何東西清楚地指明這兩個成員函數實際上的聯系,這在維護期間,會導致難以捉摸的bug。C++/CLI在對屬性的設計上,就顯得簡明多了,更接近於C#的設計,而且你還會發現,這更強大。

property String^ Name
{
String^ get()
{
return m_value;
}
void set(String^ value)
{
m_value = value;
}
}
  這是一個非常大的改進,由編譯器負責生成get_Name與set_Name方法和在此屬性中聲明的必要的元數據。更好的是,此屬性值可對程序集外部保持只讀,而對程序集內部為可寫,也可以在緊接著屬性名的花括號中使用訪問指示符來達到這一目的。

property String^ Name
{
public:
String^ get();
private public:
void set(String^);
}
  最後一點無關痛癢的事是,在那此不需要對屬性中get和set作特殊處理的地方,也可以使用簡略表示法。

property String^ Name;
  再次提醒,編譯器會生成get_Name與set_Name方法,但是這個時候,也會提供一個由private String ^ 成員變量支持的默認實現。其好處是,你可在將來某個時刻,用其他某種實現,來替換掉此處的簡易屬性,並且不會破壞類的接口。

代理

   本地C++中的函數指針,提供了一種異步執行代碼的機制,你可以存儲一個函數指針,而在以後有需要的時候及時地調用,這通常用於把某算法與實現代碼分開來,如在搜索中比較對象。另外,它也可在不同的線程中調用,以實現真實的異步編程。以下是一個ThreadPool類的簡單示例,允許你排列一系列的函數指針,並在工作者線程中執行。

class ThreadPool
{
public:

template <typename T>
static void QueueUserWorkItem(void (T::*function)(), T* object)
{
typedef std::pair<void (T::*)(), T*> CallbackType;
std::auto_ptr<CallbackType> p(new CallbackType(function, object));

if (::QueueUserWorkItem(ThreadProc<T>,
p.get(),
WT_EXECUTEDEFAULT))
{
//ThreadProc負責刪除pair.
p.release();
}
else
{
AtlThrowLastWin32();
}
}

private:

template <typename T>
static DWORD WINAPI ThreadProc(PVOID context)
{
typedef std::pair<void (T::*)(), T*> CallbackType;
std::auto_ptr<CallbackType> p(static_cast<CallbackType*>(context));
(p->second->*p->first)();
return 0;
}

ThreadPool();
};
  在C++中使用線程池是簡單兼自然的。

class Service
{
public:

void AsyncRun()
{
ThreadPool::QueueUserWorkItem(Run, this);
}

void Run()
{
//其他代碼
}
}
  很明顯,ThreadPool類是非常受限的,它只能接受特定的函數指針,這只是示例本身而不是C++本身的局限性。

  當C++程序員想要實現或得到用於異步編程的豐富庫函數時,帶著有此內置支持的CLR來了。"代理"與函數指針非常類似,除了針對的目標及方法屬於的類型(其不能決定是否一個代理可以綁定於一個給定的方法);只要類型匹配,方法就能被代理,並在以後調用,與上面使用C++模板來實現允許接受任何類成員函數的例子比較,這在思想上是相似的。當然,代理還提供了更多且極其有用的間接函數調用的機制,以下是在C++/CLI中定義一個代理類型的示例:

delegate void Function();
  使用代理也非常直截了當。

ref struct ReferenceType
{
void InstanceMethod() {}
static void StaticMethod() {}
};

//創建代理並綁定到成員函數的實例
Function^ f = gcnew Function(gcnew ReferenceType, ReferenceType::InstanceMethod);

//也可綁定到靜態成員函數,並結合幾個代理形成代理鏈
f += gcnew Function(ReferenceType::StaticMethod);

//調用函數
f();
  結束語

  關於C++/CLI,真是說上幾天也說不完,新的語言設計提供了空前的威力和絕無僅有的"優雅"語法,並且可在不犧牲簡潔性、編程效率、執行效率的情況下,完全地使用C++來編寫豐富的 .NET應用程序。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved