Zarządzane rozszerzenia dla C++

Managed Extensions for C++ lub Managed C++ to obecnie przestarzały zestaw rozszerzeń językowych dla C++ , w tym rozszerzenia gramatyczne i składniowe, słowa kluczowe i atrybuty, aby przenieść składnię i język C++ do .NET Framework . Te rozszerzenia zostały utworzone przez firmę Microsoft , aby umożliwić kierowanie kodu C++ do środowiska uruchomieniowego języka wspólnego (CLR) w postaci zarządzanego kodu , a także nadal współdziałać z kodem natywnym.

W 2004 roku rozszerzenia Managed C++ zostały znacznie zmienione, aby wyjaśnić i uprościć składnię oraz rozszerzyć funkcjonalność o zarządzane typy ogólne . Te nowe rozszerzenia zostały oznaczone jako C++/CLI i włączone do programu Microsoft Visual Studio 2005 . Termin Managed C++ i rozszerzenia, do których się odnosi, są zatem przestarzałe i zastępowane przez nowe rozszerzenia.

Historia

Firma Microsoft wprowadziła rozszerzenia zarządzane dla języka C++ w programie Microsoft Visual C++ 2002 (MSVC++). Firma Microsoft próbowała zminimalizować odchylenia między standardowym C++ a zarządzanymi rozszerzeniami dla C++, co skutkowało zaciemnieniem podstawowych różnic między tymi dwoma składniami. MSVC++ 2003 i 2005 zapewniały również obsługę pisania programów w Managed C++. W 2004 r. Managed Extensions for C++ zostało wycofane na rzecz C++/CLI , co było drugą próbą firmy Microsoft w zakresie obsługi programowania infrastruktury języka wspólnego przy użyciu języka C++.

Projekt

Zarządzany odnosi się do kodu zarządzanego , który jest uruchamiany lub zarządzany przez maszynę wirtualną platformy .NET , która działa jako piaskownica w celu zwiększenia bezpieczeństwa w postaci większej liczby kontroli czasu wykonywania, takich jak kontrole przepełnienia buforu. Ponadto aplikacje napisane w Managed C++ kompilują się do CIL — Common Intermediate Language — a nie bezpośrednio do natywnych instrukcji procesora , jak robią to standardowe aplikacje C++.

Zarządzany kod C++ może współpracować z dowolnym innym językiem również przeznaczonym dla środowiska CLR , takim jak C# i Visual Basic .NET, a także korzystać z funkcji udostępnianych przez środowisko CLR , takich jak wyrzucanie elementów bezużytecznych . Oznacza to, że Managed C++ zajmuje wyjątkową pozycję w galerii języków .NET. Jest to jedyny język, który może komunikować się bezpośrednio z językami .NET (takimi jak C#, VB.NET) oraz natywnym C++. Inne języki .NET mogą komunikować się tylko z kodem C++ za pośrednictwem PInvoke lub COM . Ale ponieważ Managed C++ może komunikować się bezpośrednio zarówno w zarządzanym, jak i standardowym kontekście C++, jest często używany jako „pomost”.

Funkcjonalność

Programy napisane w Managed C++ zapewniają dodatkową funkcjonalność .NET Framework i CLR . Najbardziej godnym uwagi z nich jest wyrzucanie elementów bezużytecznych , które zwalnia programistę z ręcznego zarządzania pamięcią. Moduł wyrzucania elementów bezużytecznych (GC) jest obsługiwany przez środowisko CLR. Zarządzanie pamięcią jest wykonywane dość szybko, ale w przypadku aplikacji o krytycznym znaczeniu dla wydajności najprawdopodobniej preferowaną opcją jest natywny, niezarządzany kod.

Managed C++ jest ukierunkowany na programowanie obiektowe. Główna różnica między standardowym C++ a zarządzanym C++ polega na tym, że dziedziczenie wielokrotne nie jest obsługiwane, a klasa zarządzana w ramach modułu wyrzucania elementów bezużytecznych CLR nie może dziedziczyć więcej niż jednej klasy. Wynika to z ograniczeń środowiska CLR.

Kluczowe cechy:

  • Rozszerzalne metadane: informacje dostarczane w celu opisania struktury i typów zarządzanego komponentu. Można go rozszerzyć i ponownie wykorzystać do tworzenia komponentów oprogramowania. Jest intensywnie używany w językach C# i Visual Basic .NET
  • Wyrzucanie śmieci: środowisko CLR jest w pełni zarządzane przez moduł wyrzucania elementów bezużytecznych do zarządzania pamięcią zautomatyzowany przez samo środowisko CLR, tj. operator usuwania nie musi być wywoływany w zarządzanym kodzie C++.
  • Interoperacyjność z językami .NET: kod przeznaczony dla .NET Framework generuje dane wyjściowe Microsoft Intermediate Language (MSIL, podobne do kodu bajtowego Java), a zatem skompilowane moduły i komponenty (raczej zespoły) mogą być ponownie wykorzystywane przez inne komponenty programu napisane w innym języku ukierunkowanym na .NET Framework, takie jak JScript .NET, C#, Visual Basic .NET i inne języki innych firm dla platformy .NET.
  • Wersjonowanie: nowe metody i elementy członkowskie danych można wprowadzać do istniejących klas zarządzanych bez naruszania zgodności binarnej z istniejącym oprogramowaniem po stronie klienta.
  • Nagłówki binarne: umożliwiają ponowne wykorzystanie prekompilowanych metadanych; do dowolnego pliku .exe, .dll, .obj lub .netmodule skompilowanego w MSIL można odwoływać się z pliku źródłowego C++.
  • Ochrona przed przepełnieniem bufora — wraz z wprowadzeniem wyrzucania elementów bezużytecznych do C++, Managed C++ jest mniej podatny na typowe błędy przepełnienia bufora spowodowane brakiem sprawdzania typu danych w standardowym C++. Garbage collector pomaga zmniejszyć (choć nie całkowicie) częstotliwość tych błędów.
  • .NET Framework Base Class Library — Managed C++ może być również mniej szczegółowy niż standardowy kod niezarządzany, ponieważ wszystkie wywołania funkcji zarządzanych i klasy dziedziczone pochodzą z biblioteki .NET Framework Base Class Library (BCL, czasami określanej jako FCL lub Framework) Class Library), którego API zapewnia możliwości sieciowe TCP/IP, funkcje manipulacji tekstem, dostęp do danych (od ODBC do SQL), usługi XML (od XSD do XSL), programowanie GUI (Windows Forms), usługi pocztowe (SMTP), kryptografia ( Certyfikaty X509 i podpisy cyfrowe XML), generowanie MSIL (zasadniczo emitowanie instrukcji w MSIL), operacje we/wy plików, ręczna manipulacja modułem wyrzucania elementów bezużytecznych CLR i zarządzanie informacjami w celu manipulowania konsolą WMI.

Przewaga nad kodem natywnym

  • Kod zarządzany i niezarządzany można bezproblemowo mieszać w tym samym zestawie CLI . Dzięki temu programista może zachować niezarządzany kod, którego nie można przenieść do .NET Framework bez całkowitego przepisania go. Istnieją jednak pewne konsekwencje stosowania tej konwencji hybrydowej.
  • Managed C++ to jedyny język, który może zawierać niezarządzany kod i natywnie komunikować się ze wszystkimi innymi językami platformy .NET. Managed C++ jest zatem bardzo wygodny dla interoperacyjności między programistami, którzy używają różnych języków, w tym tych w teatrze .NET, i tych, którzy używają standardowego C++.

Wady w porównaniu z kodem niezarządzanym

  • Managed C++ wprowadza wiele nowych słów kluczowych i konwencji składniowych, które mogą pogorszyć czytelność kodu, zwłaszcza jeśli kod C++ jest dołączony bezpośrednio i współdziała bezpośrednio z zarządzanym kodem C++ w tym samym zestawie.
  • Zarządzane C++ zostało zastąpione przez C++/CLI , a zatem przestarzałe, ponieważ C++/CLI zostało ustandaryzowane.

Wady w porównaniu z kodem w pełni zarządzanym

  • Managed C++ wymaga nieco dłuższego czasu programowania niż inne języki .NET, które można zastosować do projektów, które nadal dają te same wyniki. Użycie wskaźników może, ale nie musi być wymagane, ponieważ C++ zarządzany ma zarówno typy wartości (__value struct i __value class), jak i typy referencyjne (__gc struct i __gc class).
  • Managed C++ w pełni obsługuje aplikacje internetowe ASP.NET , mimo że tworzenie jest trudniejsze niż w przypadku innych języków .NET, w tym niektórych innych języków innych firm.
  • Managed C++ obejmuje tylko obsługę szablonów (w celu współdziałania z natywnym językiem C++), ale nie obsługuje typów ogólnych (w celu współdziałania ze wszystkimi innymi językami platformy .NET). C++/CLI obsługuje zarówno szablony (w czasie kompilacji), jak i generyczne (w czasie wykonywania).

Przykłady

Poniższe przykłady przedstawiają użycie zarządzanego języka C++ w porównaniu ze standardowym językiem C++:

  • (Zmiana globalna) Istniejący język C++, który ma zostać przeniesiony przez środowisko CLR, musi zostać uzupełniony o:






  

 

  
   0
 //hello.cpp  //nowa dyrektywa using  #using <mscorlib.dll>  //kolejna dyrektywa using namespace.  używając  przestrzeni nazw  System  ;  int  main  ()  {  Console  ::  WriteLine  (  "Witaj, świecie!"  );  powrót  ;  } 

Nowa dyrektywa preprocesora

#za pomocą<mscorlib.dll>

jest wymagane. Oprócz tego wymaganych jest więcej dyrektyw #using, aby zaimportować więcej bibliotek w celu użycia większej liczby przestrzeni nazw w Bibliotece klas podstawowych, takich jak

#za pomocą<System.Windows.Forms.dll>

I

   używając  przestrzeni nazw  System  ::  Windows  ::  Forms  ; 

korzystać z Windows Forms.

  • Aby skompilować kod do środowiska CLR, należy wprowadzić nową opcję kompilatora.
 cl.exe hello.cpp /clr 

/clr umożliwia kompilowanie dowolnego kodu odwołującego się do .NET Framework jako CIL .

  • Klasę można wyznaczyć do wyrzucania elementów bezużytecznych za pomocą słowa kluczowego rozszerzenia __gc .




   

   
   
   


 

   
  
        
  
   0
 //gc.cpp  #using <mscorlib.dll>  __gc  class  gc  {  int  *  i  ;  znak  *  g  ;  liczba zmiennoprzecinkowa  *  j  ;  };  int  main  ()  {  while  (  true  )  {  gc  ^  _gc  =  gcnew  gc  ();  }  powrót  ;  } 

Powyższy kod można skompilować i wykonać bez obaw o wycieki pamięci . Ponieważ klasa gc jest zarządzana w ramach modułu wyrzucania elementów bezużytecznych, nie ma potrzeby wywoływania operatora usuwania . Aby osiągnąć to samo z niezarządzanym kodem, wymagane jest słowo kluczowe delete :



 

   
   
   


 

   
  
        
     
  
   0
 //nogc.cpp  klasa  gc  {  int  *  i  ;  znak  *  g  ;  liczba zmiennoprzecinkowa  *  j  ;  };  int  main  ()  {  while  (  prawda  )  {  gc  *  _gc  =  nowy  gc  ();  usuń  _gc  ;  }  powrót  ;  } 

Uwagi:

  • Klasa wyznaczona przez __gc może mieć zadeklarowany konstruktor.
  • Klasa wyznaczona przez __gc może mieć zadeklarowany destruktor.
  • Klasa wyznaczona przez __gc nie może dziedziczyć więcej niż jednej klasy. (Jest to ograniczenie CLR)
  • Klasa wyznaczona przez __gc nie może dziedziczyć innej klasy, która nie jest wyznaczona przez __gc.
  • Klasa wyznaczona przez __gc nie może być dziedziczona przez inną klasę, która nie została wyznaczona przez __gc.
  • Klasa wyznaczona przez __gc może implementować dowolną liczbę interfejsów __gc.
  • Klasa wyznaczona przez __gc nie może implementować niezarządzanego interfejsu.
  • Klasa wyznaczona przez __gc domyślnie nie jest widoczna poza własnym zestawem. Używać
       publiczna  klasa  __gc  hej  {  }; 

słowo kluczowe public, aby zmodyfikować dostęp klasy wyznaczonej przez a __gc.

Klasa wyznaczona przez __gc może zostać zniszczona ręcznie przy użyciu słowa kluczowego delete, ale tylko wtedy, gdy klasa wyznaczona przez __gc ma destruktor zdefiniowany przez użytkownika.

  • Interfejs można zadeklarować poprzedzając go słowem kluczowym rozszerzenia __gc. Jak na przykład:



  

   
   
 //interface.cpp  #using <mscorlib.dll>  __gc  __interface  ClassBase  {  void  Init  ();  int  Wspólne  ();  } 

Poprzedni kod musi zostać skompilowany z /CLR i /LD, aby utworzyć prosty plik DLL.

Uwagi:

  • Interfejs __gc __ nie może zawierać żadnych elementów danych, elementów statycznych, deklaracji klas zagnieżdżonych ani specyfikatorów dostępu.
  • Interfejs __gc __ może dziedziczyć tylko z innego interfejsu interfejsu __gc __ lub System::Object. Dziedziczenie z System::Object jest zachowaniem domyślnym.
  • Interfejs __gc __ nie może zawierać żadnej implementacji (kodu treści) swoich zadeklarowanych prototypów funkcji.

Porównanie z innymi językami

Poniżej przedstawiono główne punkty i standardy programistyczne, które różnią się między Managed C++ a innymi dobrze znanymi językami programowania, które mają podobną koncepcję.

Standardowe C++

Niedogodności

  • natywny kod C++ może być szybszy w czasie wykonywania.
  • C++ nie wymaga instalacji powiązanego kompilatora i zarządzanego środowiska uruchomieniowego w systemie docelowym
  • C++ obsługuje programowanie ogólne . Jednak aż do ostatecznej wersji języka C++/CLI programiści zarządzanego języka C++ muszą powrócić do obejść związanych z używaniem typów generycznych.
  • C++ obsługuje słowo kluczowe „const” i poprawność const . Managed C++, podobnie jak Java i C#, nie zawiera tej funkcji. Alternatywą jest uczynienie klasy zarządzanej niezmienną lub ograniczenie dostępu do zestawu w interfejsach publicznych.
  • Kod C++ nie jest ograniczony przez ograniczenia CLR. Na przykład środowisko CLR nie zezwala klasom na dziedziczenie innych klas prywatnie ani nie jest chronione, dlatego poniższe spowoduje błąd kompilatora:
       
             
           public  __gc  klasa  pierwsza  {  int  i  ;  };  public  __gc  klasa  druga  :  private  one  {  int  h  ;  ja  =  h  ;  };  // błąd  public  __gc  klasa  trzecia  :  chroniony  jeden  {  int  h  ;  ja  =  h  ;};  // błąd 
  • Zarządzane klasy C++ __gc nie mogą dziedziczyć z więcej niż jednej klasy, ponieważ następujące błędy spowodują błąd kompilatora:
   
   
         __gc  klasa  a  {};  __gc  klasa  b  {};  __gc  klasa  c  :  publiczna  a  ,  publiczna  b  {};  // spowoduje błąd 

Zalety

  • Managed C++ obsługuje większy stopień odbicia niż zwykły C++, co jest ogólnie znacznie wygodniejsze w zależności od funkcji kodu lub jego przeznaczenia.
  • Managed C++ może współpracować ze wszystkimi innymi językami obsługującymi platformę .NET, w tym językami innych firm.
  • Zarządzane C++ jest wyrzucane bezużytecznie. W standardowym C++ za zarządzanie pamięcią i jej alokację odpowiada programista.

Jawa

Różnice

  • Uruchomienie kodu Java wymaga odpowiedniej maszyny wirtualnej, natomiast uruchomienie kodu Managed C++ wymaga odpowiedniej implementacji .NET Framework.

Niedogodności

  • Java zapewnia dokumentację kodu źródłowego, podczas gdy Managed C++ nie.
  • Java ma wiele innych narzędzi programistycznych dostępnych dla programistów Java, podczas gdy Managed C++ jest dostępny tylko w Visual Studio .NET .

Zalety

  • Managed C++ może uzyskać dostęp do systemu komputerowego za pomocą interfejsu niskiego poziomu znacznie łatwiej niż Java. Programiści Java muszą używać JNI (Java Native Interface), aby korzystać z usług niskiego poziomu systemu operacyjnego hosta.

C#

Różnice

  • Chociaż C# obsługuje wskaźniki tak samo jak w C++, ta funkcja jest domyślnie wyłączona.

Niedogodności

  • Podobnie jak Java , język C# jest prostszy składniowo w przypadku kodu zarządzanego.
  • C# może osiągnąć w zasadzie ten sam wynik, co Managed C++, ponieważ wszystkie konwencje składniowe i strukturalne pozostają uderzająco podobne.
  • Zarządzany C++, chociaż jest to język silnie typowany ze względu na jego wprowadzenie do CLR, może być podatny na błędy, jeśli niezarządzany skompilowany kod zostanie wprowadzony do tej samej bazy kodu, podczas gdy C# to czysty MSIL.

Zalety

  • C# musi korzystać z .NET Framework i dostarczonych bibliotek klas, aby uzyskać dostęp do systemu komputerowego na niskim poziomie.
  • Przenoszenie aplikacji do .NET Framework z języka C lub C++ jest znacznie łatwiejsze przy użyciu zarządzanego języka C++.
  • Kompilator Microsoft Visual C++ .NET, który kompiluje Managed C++ w celu obsługi .NET Framework, tworzy znacznie bardziej dojrzały zestaw instrukcji w wynikowym zestawie, co poprawia wydajność.

Zobacz też

Linki zewnętrzne