如何:定義和使用類和結構 (C++CLI)

  • 作者:由 匿名使用者 發表于 舞蹈
  • 2023-01-26

如何:定義和使用類和結構 (C++CLI)大愛研子623 2013-12-05

物件例項化 引用(ref) 型別,並且值型別只能例項化在託管堆,不在堆疊上或在本機堆。 // mcppv2_ref_class2。cpp // compile with: /clr ref class MyClass { public: int i; // nested class ref class MyClass2 { public: int i; }; // nested interface interface struct MyInterface { void f(); }; }; ref class MyClass2 : public MyClass::MyInterface { public: virtual void f() { System::Console::WriteLine(“test”); } }; public value struct MyStruct { void f() { System::Console::WriteLine(“test”); } }; int main() { // instantiate ref type on garbage-collected heap MyClass ^ p_MyClass = gcnew MyClass; p_MyClass -> i = 4; // instantiate value type on garbage-collected heap MyStruct ^ p_MyStruct = gcnew MyStruct; p_MyStruct -> f(); // instantiate value type on the stack MyStruct p_MyStruct2; p_MyStruct2。f(); // instantiate nested ref type on garbage-collected heap MyClass::MyClass2 ^ p_MyClass2 = gcnew MyClass::MyClass2; p_MyClass2 -> i = 5; }隱式抽象類 一個隱式抽象類 無法例項化。 選件類隱式是抽象的,如果選件類的基礎是介面,並選件類不實現任何介面的成員函式。 如果無法使用從從介面派生的選件類的物件,原因可能是選件類隱式是抽象的。 有關抽象類的更多資訊,請參見 摘要。 下面的程式碼示例演示,MyClass 選件類無法例項化,因為函式 MyClass::func2 未實現。 使示例生成,則取消 MyClass::func2。 // mcppv2_ref_class5。cpp // compile with: /clr interface struct MyInterface { void func1(); void func2(); }; ref class MyClass : public MyInterface { public: void func1(){} // void func2(){} }; int main() { MyClass ^ h_MyClass = gcnew MyClass; // C2259 // To resolve, uncomment MyClass::func2。 }鍵入可見性 您可以控制公共語言執行時 (CLR) 型別的可見性,以便,因此,如果程式集引用,鍵入程式集可以看到或不顯示在程式集中。 public 指示型別可見對包含程式集的一個 #using 指令包含該型別的所有原始檔。 private 指示型別不可見對包含程式集的一個 #using 指令包含該型別的原始檔。 但是,專用型別位於同一個程式集中可見的。 預設情況下,選件類的可見性是 private。 預設情況下在 Visual C++ 2005 之前,本機型別具有程式集外公共可訪問性。 使 編譯器警告(等級 1)C4692 幫助您發現位置不正確地使用私有本機型別。 使用 make_public 說明為公共可訪問性本機型別不能修改的原始碼檔案。 有關更多資訊,請參見 #using指令(C++)。 下面的示例演示如何宣告型別並指定它們的可訪問性,然後訪問在程式集中的某些型別。 當然,使用 #using,因此,如果具有專用型別的程式集引用,因此,只有程式集中的公共型別才可見。 // type_visibility。cpp // compile with: /clr using namespace System; // public type, visible inside and outside assembly public ref struct Public_Class { void Test(){Console::WriteLine(“in Public_Class”);} }; // private type, visible inside but not outside assembly private ref struct Private_Class { void Test(){Console::WriteLine(“in Private_Class”);} }; // default accessibility is private ref class Private_Class_2 { public: void Test(){Console::WriteLine(“in Private_Class_2”);} }; int main() { Public_Class ^ a = gcnew Public_Class; a->Test(); Private_Class ^ b = gcnew Private_Class; b->Test(); Private_Class_2 ^ c = gcnew Private_Class_2; c->Test(); }Output 在Public_Class 在 Private_Class_2 的 Private_Class 現在,我們覆蓋前一個示例,使其編譯為 DLL。 // type_visibility_2。cpp // compile with: /clr /LD using namespace System; // public type, visible inside and outside the assembly public ref struct Public_Class { void Test(){Console::WriteLine(“in Public_Class”);} }; // private type, visible inside but not outside the assembly private ref struct Private_Class { void Test(){Console::WriteLine(“in Private_Class”);} }; // by default, accessibility is private ref class Private_Class_2 { public: void Test(){Console::WriteLine(“in Private_Class_2”);} }; 下一個示例演示如何在程式集外訪問型別。 在該示例中,客戶端使用上一示例中生成的元件。 // type_visibility_3。cpp // compile with: /clr #using “type_visibility_2。dll” int main() { Public_Class ^ a = gcnew Public_Class; a->Test(); // private types not accessible outside the assembly // Private_Class ^ b = gcnew Private_Class; // Private_Class_2 ^ c = gcnew Private_Class_2; }Output 在Public_Class 成員可見性 您與到它的訪問從程式集外部使用對訪問說明符 public、protected和private可以減少對公共選件類成員的訪問從同一程式集的內部變數 下表彙總了各種訪問說明符的效果: 說明符 效果public 成員可訪問的內部和外部程式集。 有關更多資訊,請參見 公共(C++)。 private 成員不可訪問,以及在程式集外。 有關更多資訊,請參見 私有(C++)。 protected 成員是可訪問的於並且僅對外部程式集,但是,自派生型別。 有關更多資訊,請參見 保護(C++)。 internal 成員在程式集外是公共在程式集內,但私有的。 internal 是上下文相關關鍵字。 有關更多資訊,請參見 上下文相關的關鍵字(C++ 元件擴充套件)。 public protected -or- protected public 成員是公共在程式集內,但在程式集外保護。 private protected -or- protected private 保護成員在程式集內,但在私有程式集中。 下面的示例顯示具有成員聲明瞭不同的可訪問性,然後顯示訪問這些成員從程式集內的公共型別。 // type_member_visibility。cpp // compile with: /clr using namespace System; // public type, visible inside and outside the assembly public ref class Public_Class { public: void Public_Function(){System::Console::WriteLine(“in Public_Function”);} private: void Private_Function(){System::Console::WriteLine(“in Private_Function”);} protected: void Protected_Function(){System::Console::WriteLine(“in Protected_Function”);} internal: void Internal_Function(){System::Console::WriteLine(“in Internal_Function”);} protected public: void Protected_Public_Function(){System::Console::WriteLine(“in Protected_Public_Function”);} public protected: void Public_Protected_Function(){System::Console::WriteLine(“in Public_Protected_Function”);} private protected: void Private_Protected_Function(){System::Console::WriteLine(“in Private_Protected_Function”);} protected private: void Protected_Private_Function(){System::Console::WriteLine(“in Protected_Private_Function”);} }; // a derived type, calls protected functions ref struct MyClass : public Public_Class { void Test() { Console::WriteLine(“=======================”); Console::WriteLine(“in function of derived class”); Protected_Function(); Protected_Private_Function(); Private_Protected_Function(); Console::WriteLine(“exiting function of derived class”); Console::WriteLine(“=======================”); } }; int main() { Public_Class ^ a = gcnew Public_Class; MyClass ^ b = gcnew MyClass; a->Public_Function(); a->Protected_Public_Function(); a->Public_Protected_Function(); // accessible inside but not outside the assembly a->Internal_Function(); // call protected functions b->Test(); // not accessible inside or outside the assembly // a->Private_Function(); }Output 在Public_Function 在 Protected_Public_Function 在 Internal_Function ======================= 的 Public_Protected_Function 在派生類的功能。Protected_Function 在 Protected_Private_Function 在退出派生類 ======================= 的功能 Private_Protected_Function 現在我們生成前面的示例作為 DLL。 // type_member_visibility_2。cpp // compile with: /clr /LD using namespace System; // public type, visible inside and outside the assembly public ref class Public_Class { public: void Public_Function(){System::Console::WriteLine(“in Public_Function”);} private: void Private_Function(){System::Console::WriteLine(“in Private_Function”);} protected: void Protected_Function(){System::Console::WriteLine(“in Protected_Function”);} internal: void Internal_Function(){System::Console::WriteLine(“in Internal_Function”);} protected public: void Protected_Public_Function(){System::Console::WriteLine(“in Protected_Public_Function”);} public protected: void Public_Protected_Function(){System::Console::WriteLine(“in Public_Protected_Function”);} private protected: void Private_Protected_Function(){System::Console::WriteLine(“in Private_Protected_Function”);} protected private: void Protected_Private_Function(){System::Console::WriteLine(“in Protected_Private_Function”);} }; // a derived type, calls protected functions ref struct MyClass : public Public_Class { void Test() { Console::WriteLine(“=======================”); Console::WriteLine(“in function of derived class”); Protected_Function(); Protected_Private_Function(); Private_Protected_Function(); Console::WriteLine(“exiting function of derived class”); Console::WriteLine(“=======================”); } }; 下面的示例如何使用上一示例中建立的元素從而顯示訪問成員從程式集外部。 // type_member_visibility_3。cpp // compile with: /clr #using “type_member_visibility_2。dll” using namespace System; // a derived type, calls protected functions ref struct MyClass : public Public_Class { void Test() { Console::WriteLine(“=======================”); Console::WriteLine(“in function of derived class”); Protected_Function(); Protected_Public_Function(); Public_Protected_Function(); Console::WriteLine(“exiting function of derived class”); Console::WriteLine(“=======================”); } }; int main() { Public_Class ^ a = gcnew Public_Class; MyClass ^ b = gcnew MyClass; a->Public_Function(); // call protected functions b->Test(); // can‘t be called outside the assembly // a->Private_Function(); // a->Internal_Function(); // a->Protected_Private_Function(); // a->Private_Protected_Function(); }Output 在派生類中函式的 Public_Function ======================= 在 Protected_Function 在 Protected_Public_Function 在退出派生類 ======================= 的功能 Public_Protected_Function 公共和私有本機選件類 本機型別可以從託管型別引用。 例如,在託管型別的函式會採用型別是本機結構的引數。 如果託管和函式的型別是公共的程式集中,則本機型別也必須是公共的。 // mcppv2_ref_class3。h // native type public struct N { N(){} int i; }; 接下來,建立一個使用本機型別的原始碼檔案: // mcppv2_ref_class3。cpp // compile with: /clr /LD #include “mcppv2_ref_class3。h” // public managed type public ref struct R { // public function that takes a native type void f(N nn) {} }; 現在,請生成客戶端: // mcppv2_ref_class4。cpp // compile with: /clr #using “mcppv2_ref_class3。dll” #include “mcppv2_ref_class3。h” int main() { R ^r = gcnew R; N n; r->f(n); }靜態建構函式 CLR 型別 (例如,選件類或結構可以具有可用於初始化靜態資料成員的靜態建構函式。 該型別的所有靜態成員首次,訪問靜態建構函式呼叫最多一次呼叫和。 例項建構函式始終執行靜態建構函式。 如果選件類具有靜態建構函式,編譯器不能內聯呼叫建構函式。 編譯器無法內聯對函式的任何成員,如果選件類是值型別,具有靜態建構函式和沒有例項建構函式。 CLR 可以內聯呼叫,但是,編譯器無法。 因為被視為由 CLR,僅呼叫定義靜態建構函式作為私有成員函式。 有關靜態建構函式的更多資訊,請參見 如何:定義介面靜態建構函式 (C++/CLI)。 // mcppv2_ref_class6。cpp // compile with: /clr using namespace System; ref class MyClass { private: static int i = 0; static MyClass() { Console::WriteLine(“in static constructor”); i = 9; } public: static void Test() { i++; Console::WriteLine(i); } }; int main() { MyClass::Test(); MyClass::Test(); }Output 在靜態建構函式 10 11 此指標的語義 當使用 Visual C++ 定義型別時,在引用型別的 this 指標為型別“handles”。 在值型別的 this 指標為型別“內部指標”。 儘管預設值索引器呼叫時,這些 this 指標的語義不同可能導致意外行為。 下一個示例顯示正確方法訪問一個預設值索引器在 ref 型別和值型別。 有關更多資訊,請參見 物件控制代碼運算子 (^)(C++ 元件擴充套件) interior_ptr (C++/CLI) 如何:使用索引屬性// semantics_of_this_pointer。cpp // compile with: /clr using namespace System; ref struct A { property Double default[Double] { Double get(Double data) { return data*data; } } A() { // accessing default indexer Console::WriteLine(“{0}”, this[3。3]); } }; value struct B { property Double default[Double] { Double get(Double data) { return data*data; } } void Test() { // accessing default indexer Console::WriteLine(“{0}”, this->default[3。3]); } }; int main() { A ^ mya = gcnew A(); B ^ myb = gcnew B(); myb->Test(); }Output 10。89 10。89 隱藏由簽名功能 在標準 C++ 中,在基類中的函式由具有相同名稱在派生類中隱藏功能,因此,即使派生類功能具有相同數量或引數。 這稱為“ 按名稱隱藏 語義。 在引用型別,因此,如果該名稱和引數列表相同,在基類中的函式可以按功能僅隱藏在派生類。 這稱為” 隱藏由簽名 語義。 當其所有函式在元資料標記為 hidebysig時,選件類被視為隱藏由簽名選件類。 預設情況下,建立在 /clr 下的所有選件類具有 hidebysig 功能。 但是,編譯使用 /clr:oldSyntax 的選件類沒有 hidebysig 功能;相反,它們是隱藏按名排序功能。 當選件類具有 hidebysig 功能時,編譯器將任何不按名稱隱藏功能直接基類,但是,如果編譯器遇到在繼承鏈中隱藏按名稱選件類,將繼續該隱藏按名排序行為。 隱藏由簽名語義下,那麼,當函式呼叫物件時,編譯器確定包含一個功能可以滿足函式呼叫的派生類。 如果只有在無法滿足呼叫的選件類中的函式,編譯器呼叫該函式。 如果存在多個可以滿足呼叫的選件類中的函式,編譯器使用 hyper-v 載入決策規則確定要呼叫的函式。 有關超載入規則的更多資訊,請參見 函式過載、“。 對於特定函式呼叫,在基類中的函式可能具有與在派生類中的函式使其成為稍微好的匹配的簽名。 但是,在中,如果函式顯式呼叫該派生類的物件,派生類中的函式呼叫。 由於返回值不被視為一部分的函式的簽名,一個基類功能隱藏,如果它具有相同名稱和取出操作的數量和種類引數和一個派生類功能相同,因此,即使在返回值的型別不同。 下面的示例顯示,在基類中的函式不受功能隱藏在派生類。 // hide_by_signature_1。cpp // compile with: /clr using namespace System; ref struct Base { void Test() { Console::WriteLine(”Base::Test“); } }; ref struct Derived : public Base { void Test(int i) { Console::WriteLine(”Derived::Test“); } }; int main() { Derived ^ t = gcnew Derived; // Test() in the base class will not be hidden t->Test(); }Output Base::Test 下面的示例演示,Visual C++ 編譯器會在派生的類選件均勻的函式,如果需要轉換匹配一個或多個引數和不呼叫是一個更好的最為匹配的基類的一個函式呼叫。 // hide_by_signature_2。cpp // compile with: /clr using namespace System; ref struct Base { void Test2(Single d) { Console::WriteLine(”Base::Test2“); } }; ref struct Derived : public Base { void Test2(Double f) { Console::WriteLine(”Derived::Test2“); } }; int main() { Derived ^ t = gcnew Derived; // Base::Test2 is a better match, but the compiler // calls a function in the derived class if possible t->Test2(3。14f); }Output Derived::Test2 下面的示例演示,隱藏功能是可能的,即使該基類具有簽名和派生類相同。 // hide_by_signature_3。cpp // compile with: /clr using namespace System; ref struct Base { int Test4() { Console::WriteLine(”Base::Test4“); return 9; } }; ref struct Derived : public Base { char Test4() { Console::WriteLine(”Derived::Test4“); return ’a‘; } }; int main() { Derived ^ t = gcnew Derived; // Base::Test4 is hidden int i = t->Test4(); Console::WriteLine(i); }Output Derived::Test4 97 下面的示例定義了使用 /clr:oldSyntax,生成的一個元素。 定義使用 C++ 託管擴充套件的選件類具有隱藏按名成員函式。

Top