Aracılığıyla paylaş


Nasıl yapılır: Sınıfları ve Yapıları Tanımlama ve Kullanma (C++/CLI)

Bu makalede nasıl tanımlanacağını ve değer türleri ve başvuru kullanıcı tanımlı türleri tüketme gösterir C++/CLI.

Nesne Örneğini Oluşturmada

Değer türleri ve başvuru (ref) türleri, yalnızca yönetilen yığında, yığında veya yerel yığında oluşturulabilir.

// 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;
}

Dolaylı olarak soyut sınıflar

Bir dolaylı olarak sınıf soyut örneği oluşturulamıyor.Bir temel sınıf bir arabirim türüdür ve sınıf tüm üye işlevleri arabirim uygulamıyor dolaylı olarak soyut sınıftır.

Bir arabirimden türetilmiş bir sınıftan nesneleri oluşturmak, dolaylı olarak soyut sınıf neden olabilir.Soyut sınıflar hakkında daha fazla bilgi için bkz: soyut.

Aşağıdaki kod örneği gösteren MyClass sınıfı olamaz örneği olduğundan işlev MyClass::func2 henüz uygulanmadı.Örnek derlemek etkinleştirmek için açıklama karakterlerini kaldırın 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.
}

Görünürlük türü

Bir bütünleştirilmiş koda başvurulduğunda, derlemedeki türleri görünür veya görünmez derleme dışına olabilir böylece ortak dil çalışma zamanı (clr) türleri görünürlüğünü kontrol edebilirsiniz.

publictürü içeren herhangi bir kaynak dosyası görünür olduğunu gösteren bir #using türü içeren derleme yönergesi.privatebir tür içeren kaynak dosyaları görünür değil gösterir bir #using türü içeren derleme yönergesi.Ancak, özel türleri aynı derlemenin içinde görülebilir.Varsayılan olarak, bir sınıf için görünürlüğü olan private.

Visual c++ 2005 önce varsayılan olarak, yerel türler genel erişilebilirlik derleme dışına vardı.Etkinleştirme Derleyici uyarı (düzey 1) C4692 özel yerel türler yanlış nerede kullanıldığını görmenize yardımcı olacak.Kullanım make_public pragma değiştiremeyeceğiniz bir kaynak kodu dosyası yerel tür genel erişilebilirlik vermek için.

Daha fazla bilgi için bkz. # kullanma yönergesi (C++).

Aşağıdaki örnek türleri bildirmek ve bunların erişilebilirlik belirtin ve sonra bu derleme içindeki türler erişmek nasıl gösterir.Kullanarak özel türleri olan bir bütünleştirilmiş koda başvurulduğunda, Kurs #using, sadece ortak türleri derlemedeki görülebilir.

// 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();
}

Çıktı

  

Şimdi, bakalım dll olarak kurulmuştur böylece önceki örneği yeniden yazmak.

// 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");}
};

Sonraki örnek, derleme dışına türlerine erişmek gösterilmiştir.Bu örnek, önceki örnekte oluşturulan bileşeni istemci tüketir.

// 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;
}

Çıktı

  

Üye görünürlüğü

Access aynı bütünleştirilmiş kod içinde bir ortak sınıf üyesi için farklı erişim içinden derlemenin dışından erişim belirticileri çiftlerini kullanarak yapabileceğiniz public, protected, veprivate

Bu tablo çeşitli erişim belirticileri etkisini özetler:

Belirleyici

Etki

public

İç ve dış derleme erişilebilir üyesidir.Daha fazla bilgi için bkz. Ortak (C++).

private

Üye içinde ne derleme dışına erişilebilir değil.Daha fazla bilgi için bkz. Özel (C++).

protected

İçinde ve dışında derleme, ancak yalnızca türetilmiş türleri erişilebilir üyesidir.Daha fazla bilgi için bkz. korumalı (C++).

internal

Genel bütünleştirilmiş kod içinde ancak özel derleme dışına üyesidir.internalbağlama duyarlı bir anahtar sözcüktür.Daha fazla bilgi için bkz. Bağlama Duyarlı Anahtar Sözcükler (C++ Bileşen Uzantıları).

public protected
-or-
protected public

Genel bütünleştirilmiş kod içinde ancak derleme dışına korumalı üyesidir.

private protected
-or-
protected private

Derleme içinde korunan, ancak özel derleme dışına üyesidir.

Aşağıdaki örnek ile farklý eriþebilirlik bildirilen üyeleri olan ortak bir türü gösterir ve daha sonra derleme içindeki bu üyelerinden erişme gösterir.

// 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();
}

Çıktı

  

Şimdi gelin bir dll olarak önceki örneği oluşturmak.

// 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("=======================");
   }
};

Aşağıdaki örnek, önceki örnekte oluşturulan ve dolayısıyla üyelerinden derleme dışına ReportOrders bileşen tüketir.

// 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();
}

Çıktı

  

Ortak ve özel yerel sınıflar

Yerel tür yönetilen bir türden başvurulabilir.Örneğin, yönetilen tür bir işlevi doğal bir yapı türü olan bir parametre alabilir.Daha sonra yerel türü bir derlemede ortak işlev ve yönetilen türünü de public olmalıdır.

// mcppv2_ref_class3.h
// native type
public struct N {
   N(){}
   int i;
};

Sonra yerel türü kullanır kaynak kodu dosyası oluşturun:

// 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) {}
};

Şimdi, bir istemci derleme:

// 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);
}

Statik oluşturucular

clr türü — örneğin, bir sınıf veya yapı birimi — statik veri üyeleri başlatmak için kullanılan bir statik oluşturucuya sahip.Statik oluşturucu en fazla bir kez çağrılır ve türü herhangi bir statik üyesi ilk kez erişmeden önce çağrılır.

Örnek oluşturucu sonra statik oluşturucu her zaman çalışır.

Sınıf statik oluşturucu varsa derleyici satır içi bir kurucu çağrısı yapılamaz.Sınıf bir değer türü, statik oluşturucuya sahip örnek oluşturucu yok ise derleyici satır içi herhangi bir üye işlevine bir çağrı yapamazsınız.Satır içi arama clr olabilir, ancak derleyici olamaz.

clr tarafından çağrılacak taşıdığından statik oluşturucu özel üye işlev olarak tanımlayın.

Statik oluşturucular hakkında daha fazla bilgi için bkz: Nasıl yapılır: Arabirim Statik Oluşturucusunu Tanımlama (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();
}

Çıktı

  

Bu semantiği işaretçi

Visual c++ kullanırken, tanımlamak için this işaretçiyi bir başvuru türü olan "tanıtıcı" tür.this Bir değer türü işaretçi türüdür "iç işaretçi".

Bu farklı semantiği this işaretçi beklenmeyen davranışlara neden olabilir varsayılan dizin oluşturucu çağrılırken.Sonraki örnek, hem bir başvuru türü ve değer türü varsayılan oluşturucuda erişmek için doğru şekilde gösterir.

Daha fazla bilgi için,

// 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();
}

Çıktı

  

Gizle imza işlevleri

Türetilmiş sınıf işlevi aynı numarayı veya tür parametreleri yoksa bile, standart C++'da, bir taban sınıftaki bir işlev türetilmiş bir sınıf içinde aynı ada sahip bir işlev tarafından gizli.Bu olarak bilinir ada göre Gizle semantiği.Hem adı hem de parametre listesi aynı olması durumunda bir başvuru türü bir taban sınıftaki bir işlev yalnızca türetilmiş bir sınıf içinde bir işlev tarafından gizlenebilir.Olarak bilinen bu Gizle imza semantiği.

Tüm işlevlerini meta işaretlendiğinde Gizle imza sınıfı bir sınıf olarak kabul edilir hidebysig.Varsayılan olarak, altında oluşturulan tüm sınıfları /clr sahip hidebysig işlevleri.Ancak, kullanarak derlenmiş bir sınıf /clr:oldSyntax sahip hidebysig işlev görür; Bunun yerine, bunlar ada göre Gizle işlevlerdir.Ne zaman bir sınıf olan hidebysig İşlevler, derleyici olmayan işlevleri doğrudan herhangi bir temel sınıf adını yazarak gizlemek, ancak derleyici kalıtım zincirini ada göre Gizle sınıfında karşılaşırsa, o ada göre gizleme davranışını devam eder.

Bir nesne üzerinde bir işlev çağrıldığında Gizle imza semantiği altında derleyici işlev çağrısı karşılayan bir işlev içeren en türetilmiş sınıf tanımlar.Derleyicinin çağrıyı karşılayan sınıfında tek bir işlevi ise, o işlevini çağırır.Çağrı karşılayan sınıfında birden fazla işlevi ise, derleyici kullanır hangi işlevi çağırmak için belirlemek için çözümleme kurallarını tekrar.Aşırı kuralları hakkında daha fazla bilgi için bkz: Aşırı çalışması.

Verilen işlev çağırmak için türetilmiş bir sınıf içinde bir işlev daha biraz daha iyi bir eşleşme sağlayan bir imza bir taban sınıftaki bir işlev olabilir.İşlev türetilmiş sınıf bir nesne üzerinde açıkça çağrıldı, ancak, türetilmiş sınıf içinde işlevi çağrılır.

Dönüş değeri bir işlevin imzası bir parçası olarak kabul edilmez çünkü dönüş değeri türü içinde farklı olsa da, aynı ada sahip ve aynı sayıda ve türde bağımsız değişkenler, bir türetilmiş sınıf işlev alır, temel sınıf işlevi gizlidir.

Aşağıdaki örnek bir taban sınıftaki bir işlev türetilmiş bir sınıf içinde bir işlev tarafından gizli değil olduğunu gösterir.

// 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();
}

Çıktı

  

Sonraki örnek Visual c++ derleyicisi en türetilmiş bir sınıf içindeki bir işlev çağrılarını gösterir — bir dönüştürme bir veya daha fazla parametre eşleşmesi gereken bile — ve bir işlev çağrısı için daha iyi eşleşen bir taban sınıftaki ilevini değil.

// 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);
}

Çıktı

  

Aşağıdaki örnek, bir işlev temel sınıf türetilmiş bir sınıf olarak aynı imzaya sahip olsa bile gizlemek olası olduğunu gösterir.

// 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);
}

Çıktı

  

Aşağıdaki örnek kullanarak derlenmiş bir bileşeni tanımlayan /clr:oldSyntax.c++ için Yönetilen Uzantılar kullanılarak tanımlanmış sınıflar, ada göre Gizle üye işlevleri vardır.

// hide_by_signature_4.cpp
// compile with: /clr:oldSyntax /LD
using namespace System;
public __gc struct Base0 {
   void Test() { 
      Console::WriteLine("in Base0::Test");
   }
};

public __gc struct Base1 : public Base0 {
   void Test(int i) { 
      Console::WriteLine("in Base1::Test");
   }
};

Sonraki örnek, önceki örnekte oluşturulan bileşen tüketir.Bildirimi nasıl Gizle-tarafından-imza işlevini kullanarak derlenmiş türlerinin temel sınıflar için uygulanan değil /clr:oldSyntax.

// hide_by_signature_5.cpp
// compile with: /clr:oldSyntax /LD
// compile with: /clr
using namespace System;
#using "hide_by_signature_4.dll"

ref struct Derived : public Base1 {
   void Test(int i, int j) { 
      Console::WriteLine("Derived::Test");
   }
};

int main() {
   Derived ^ t = gcnew Derived;
   t->Test(8, 8);   // OK
   t->Test(8);   // OK
   t->Test();   // C2661
}

Kopya oluşturucuları

c++ standart bir nesne oluşturulur ve aynı adreste yok, bir nesne taşındığında kopya oluşturucusuna adlı diyor.

Ancak, ne zaman /clr derleme ve yerel sınıfı burada yerel bir işlev çağrıları MSIL derlenmiş bir işlev için kullanılır — veya birden fazla — değerine göre ve burada yerel sınıfı bir kopya oluşturucusuna ve/veya yıkıcı olan, hiçbir kopya kurucusu çağrılır ve nesnenin oluşturulduğu'den farklı bir adreste yok geçirilir.Sınıfın kendisi içine bir işaretçi varsa veya nesneleri adresine göre izleme kodu olan bu sorunlara neden olabilir.

Daha fazla bilgi için bkz. /CLR (ortak dil çalışma zamanı derleme).

Aşağıdaki örnek bir kopya oluşturucusuna değil oluşturulduğunda gösterir.

// breaking_change_no_copy_ctor.cpp
// compile with: /clr
#include<stdio.h>

struct S {
   int i;
   static int n;

   S() : i(n++) { 
      printf_s("S object %d being constructed, this=%p\n", i, this); 
   }

   S(S const& rhs) : i(n++) { 
      printf_s("S object %d being copy constructed from S object "
               "%d, this=%p\n", i, rhs.i, this); 
   }

   ~S() {
      printf_s("S object %d being destroyed, this=%p\n", i, this); 
   }
};

int S::n = 0;

#pragma managed(push,off)
void f(S s1, S s2) {
   printf_s("in function f\n");
}
#pragma managed(pop)

int main() {
   S s;
   S t;
   f(s,t);
}

Çıktı

  

Yıkıcı ve sonlandırıcılar

Yıkıcı bir başvuru türü'nde bir deterministic temizleme kaynakların gerçekleştirin.Sonlandırıcılar yönetilmeyen kaynakları temizlemek ve kilidinin yıkıcı veya nondeterministically Çöp toplayıcı tarafından çağrılabilir.Standart C++'ta Yıkıcılar hakkında daha fazla bilgi için bkz: Yıkıcılar (C++).

class classname {
   ~classname() {}   // destructor
   ! classname() {}   // finalizer
};

Yönetilen bir Visual c++ sınıfındaki yıkıcı davranışları c++ için Yönetilen Uzantılar'dan farklıdır.Bu değişiklik hakkında daha fazla bilgi için bkz: Yok Edici Anlamında Yapılan Değişiklikler.

clr Çöp toplayıcı kullanılmayan yönetilen nesneleri siler ve artık gerekli olduklarında kendi belleği serbest bırakır.Ancak, bir tür Çöp toplayıcı nasıl serbest bırakılacağı bilmez kaynakları kullanabilir.Yönetilmeyen kaynaklar olarak bilinen bu kaynaklar (yerel dosya işleme, örneğin).Sonlandırıcı tüm yönetilmeyen kaynakları serbest bırakmak öneririz.Yönetilen kaynaklar nondeterministically çöp toplayıcısı tarafından yayımlanan çünkü mümkün olduğundan bir sonlandırıcı olarak yönetilen kaynaklar Çöp toplayıcı zaten o yönetilen kaynak temizledi başvurmak güvenli değil.

Visual c++ sonlandırıcıyı aynı değil Finalize yöntem.(clr belgelerinde Sonlandırıcı kullanır ve Finalize yöntemi maliyetle aynı anlamda).Finalize Yöntemini çağıran bir sınıf devralma zincirindeki her sonlandırıcıyı Çöp toplayıcı tarafından çağrılır.Visual c++ yıkıcı farklı olarak, tüm temel sınıfları sonlandırıcıyı çağırmak derleyici türetilmiş sınıf sonlandırıcıyı çağrı neden olmaz.

Visual c++ derleyicisi kaynakları kararlı sürümünün desteklediğinden, gerçekleştirmeyi denemeyin Dispose veya Finalize yöntemleri.Ancak, bu yöntemleri ile bilginiz varsa, işte nasıl bir Visual c++ Sonlandırıcı ve sonlandırıcı çağıran bir yıkıcı eşleştirmek Dispose deseni:

// Visual C++ code
ref class T {
   ~T() { this->!T(); }   // destructor calls finalizer
   !T() {}   // finalizer
};

// equivalent to the Dispose pattern
void Dispose(bool disposing) {
   if (disposing) {
      ~T();
   } else {
      !T();
   }
}

Yönetilen tür kilidinin bırakın ve sonra nesne artık gerekli değil belirli bir noktada nondeterministically serbest bırakmak için çöp toplayıcı bırakmamaya tercih yönetilen kaynaklar da kullanabiliriz.Kaynakları kararlı sürümü performansını önemli ölçüde artırabilirsiniz.

Visual c++ derleyicisi kilidinin nesneleri temizleyeceği için yıkıcı bir tanımını sağlar.Yıkıcı kilidinin serbest bırakmak istediğiniz tüm kaynakları serbest bırakmak için kullanın.Bir sonlandırıcı varsa, kod yinelenmesini önlemek için yıkıcı çağırın.

// destructors_finalizers_1.cpp
// compile with: /clr /c
ref struct A {
   // destructor cleans up all resources
   ~A() {
      // clean up code to release managed resource
      // ...
      // to avoid code duplication, 
      // call finalizer to release unmanaged resources
      this->!A();
   }

   // finalizer cleans up unmanaged resources
   // destructor or garbage collector will
   // clean up managed resources
   !A() {
      // clean up code to release unmanaged resources
      // ...
   }
};

Yıkıcı türünüzü tüketir kod çağırmaz, çöp toplayıcı sonunda yönetilen tüm kaynakları serbest bırakır.

Bir yıkıcı varlığını bir sonlandırıcı varlığını göstermez.Ancak, bir sonlandırıcı varlığını bir yıkıcı tanımlayın ve sonlandırıcı o yıkıcıdan çağırmak anlamına gelir.Bu yönetilmeyen kaynakları kararlı sürümü için sağlar.

Yıkıcı çağırma bastırır — kullanarak SuppressFinalize— nesnenin sonlandırılması.Yıkıcı çağrılmazsa tipi iş sonlandırıcıyı sonunda çöp toplayıcısı tarafından denir.

Yıkıcı çağırarak, nesnenin kaynakları kilidinin temizleme izin vererek nondeterministically nesne sonlandırma clr ile karşılaştırıldığında performansı artırabilir.

Visual c++ ile yazılmış ve ile derlenmiş kodu /clr bir türün yıkıcı çalıştırır:

Yıkıcı türünüzü başka bir dilde yazılan bir istemci tarafından Tüketilmekte olan, aşağıdaki gibi verilir:

  • Yapılan çağrı sırasında Dispose.

  • Yapılan çağrı sırasında Dispose(void) türü.

  • C# [NULL]'ta kapsam türü gider, using ifadesi.

(Başvuru türleri için yığın semantiği kullanmayan) yönetilen yığında bir başvuru türünde bir nesne oluşturursanız, kullanın try finally sözdizimini kullanarak bir özel durum yıkıcı çalışmasına engel değil emin olun.

// clr_destructors.cpp
// compile with: /clr
ref struct A {
   ~A() {}
};

int main() {
   A ^ MyA = gcnew A;
   try {
      // use MyA
   }
   finally {
      delete MyA;
   }
}

Türünüzü bir yıkıcı varsa, derleyicinin oluşturduğu bir Dispose yöntemi uygulayan IDisposable.Visual c++ ile yazılmış ve başka bir dilden tüketilen bir yıkıcı olan bir türü, arama IDisposable::Dispose bu tür üzerinde çağrılacak türün yıkıcı neden olur.Visual c++ istemciden türü tüketildiğinde, doğrudan çağrılamaz Dispose; Bunun yerine, yıkıcı kullanarak arama delete işleci.

Türünüzü bir sonlandırıcı varsa, derleyici oluşturduğu bir Finalize(void) yöntemi geçersiz kılar Finalize.

Bir tür bir sonlandırıcı veya bir yıkıcı varsa, derleyici oluşturduğu bir Dispose(bool) göre Tasarım deseni yöntemi.(Bilgi için bkz: Implementing Finalize and Dispose to Clean Up Unmanaged Resources).Siz açıkça Yazar arayın veya Dispose(bool) Visual C++'ta.

Tasarım desene uyan bir temel sınıf türündeyse, türetilmiş sınıf yıkıcı çağrıldığında için tüm temel sınıflar yıkıcı olarak adlandırılır.(Visual c++'ta türünüzü yazılmışsa, derleyici türlerinizi bu deseni uygulayan sağlar.) Diğer bir deyişle, başvuru sınıf yıkıcı, tabanlar ve c++ standart tarafından belirtilen üyelerine bağlanır — sınıfın yıkıcı çalışma, daha sonra bunlar parçalarından sırasının ters kendi üyeleri için yıkıcı olduğu ilk ve son yıkıcı temel sınıflarının tersine, bunlar parçalarından sipariş için.

Yıkıcı ve sonlandırıcılar değer türleri veya arabirimler içinde izin verilmez.

Bir sonlandırıcı yalnızca tanımlanan veya bir başvuru türü bildirilir.Yapıcı ve yıkıcı olduğu gibi bir sonlandırıcı hiçbir dönüş türüne sahip.

Nesnenin sonlandırıcıyı çalıştıktan sonra az türetilmiş bir tür ile başlayan sonlandırıcılar herhangi bir temel sınıflar olarak da bilinir.Sonlandırıcılar veri üyeleri için otomatik olarak için sınıf Sonlandırıcı tarafından zincirlenir değil.

Yerel bir işaretçi yönetilen türde bir sonlandırıcı silerse, başvurular ya da yerel işaretçi üzerinden değil zamanından önce toplanan olduğunu emin olmalısınız; yerine yönetilen tür yýkýcýyý çaðýrmak KeepAlive.

Derleme zamanında bir yıkıcı veya bir sonlandırıcı türüne sahip olup olmadığını algılayabilir.Daha fazla bilgi için bkz. Tür Özellikleri için Derleyici Desteği (C++ Bileşen Uzantıları).

Sonraki örnek iki türü, yönetilmeyen kaynakları olan biri ve kilidinin yayımlanan kaynaklar yönettiği bir gösterir.

// destructors_finalizers_2.cpp
// compile with: /clr
#include <vcclr.h>
#include <stdio.h>
using namespace System;
using namespace System::IO;

ref class SystemFileWriter {
   FileStream ^ file;
   array<Byte> ^ arr;
   int bufLen;

public:
   SystemFileWriter(String ^ name) : file(File::Open(name, FileMode::Append)), 
                                     arr(gcnew array<Byte>(1024)) {}

   void Flush() {
      file->Write(arr, 0, bufLen);
      bufLen = 0;
   }

   ~SystemFileWriter() {
      Flush();
      delete file;
   }
};

ref class CRTFileWriter {
   FILE * file;
   array<Byte> ^ arr;
   int bufLen;

   static FILE * getFile(String ^ n) {
      pin_ptr<const wchar_t> name = PtrToStringChars(n);
      FILE * ret = 0;
      _wfopen_s(&ret, name, L"ab");
      return ret;
   }

public:
   CRTFileWriter(String ^ name) : file(getFile(name)), arr(gcnew array<Byte>(1024) ) {}

   void Flush() {
      pin_ptr<Byte> buf = &arr[0];
      fwrite(buf, 1, bufLen, file);
      bufLen = 0;
   }

   ~CRTFileWriter() {
      this->!CRTFileWriter();
   }

   !CRTFileWriter() {
      Flush();
      fclose(file);
   }
};

int main() {
   SystemFileWriter w("systest.txt");
   CRTFileWriter ^ w2 = gcnew CRTFileWriter("crttest.txt");
}

Ayrıca bkz.

Başvuru

Sınıflar ve Yapılar (C++ Bileşen Uzantıları)

Sınıflar ve Yapılar (C++ Bileşen Uzantıları)