C++/CLI

C++/CLI
Paradigm Strukturerad , imperativ , objektorienterad
Familj C
Designad av Microsoft
Utvecklare Microsoft
Dök först upp 2005 ; 18 år sedan ( 2005 )
Plattform Gemensam språkinfrastruktur
Hemsida docs .microsoft .com /en-us /cpp / dotnet /dotnet-programming-with-cpp-cli-visual-cpp
Influerad av
C++ , Managed Extensions för C++ , C #

C++/CLI är en variant av programmeringsspråket C++ , modifierat för Common Language Infrastructure . Det har varit en del av Visual Studio 2005 och senare och ger interoperabilitet med andra .NET- språk som C# . Microsoft skapade C++/CLI för att ersätta Managed Extensions för C++ . I december 2005 Ecma International C++/CLI-specifikationer som ECMA-372 -standarden.

Syntaxändringar

C++/CLI bör ses som ett eget språk (med en ny uppsättning nyckelord, till exempel), istället för det C++ superset-orienterade Managed C++ (MC++) (vars icke-standardiserade nyckelord var utformade som __gc eller __value ) . På grund av detta finns det några stora syntaktiska förändringar, särskilt relaterade till elimineringen av tvetydiga identifierare och tillägget av .NET-specifika funktioner.

Många motstridiga syntaxer, som de flera versionerna av operatorn new () i MC++, har delats: i C++/CLI skapas .NET-referenstyper med det nya nyckelordet gcnew (dvs. garbage collected new()). Dessutom har C++/CLI introducerat konceptet med generika från .NET (liknande, för de vanligaste syftena, till standard C++-mallar, men helt olika i deras implementering).

Handtag

I MC++ fanns det två olika typer av pekare : __nogc- pekare var normala C++-pekare, medan __gc -pekare fungerade på .NET-referenstyper. I C++/CLI är dock den enda typen av pekare den vanliga C++-pekaren, medan .NET-referenstyperna nås via ett "handtag", med den nya syntaxen ClassName ^ ( istället för ClassName * ) . Denna nya konstruktion är särskilt användbar när hanterad och standard C++-kod blandas; det klargör vilka objekt som är under .NET automatisk sophämtning och vilka objekt som programmeraren måste komma ihåg att explicit förstöra.

Spårningsreferenser

En spårningsreferens i C++/CLI är ett handtag för en överförd referensvariabel. Det liknar konceptet att använda " *& " (referens till en pekare) i standard C++, och (i funktionsdeklarationer) motsvarar nyckelordet " ref " som tillämpas på typer i C#, eller " ByRef " i Visual Basic .NET . C++/CLI använder en " ^% "-syntax för att indikera en spårningsreferens till ett handtag.

Följande kod visar ett exempel på användning av spårningsreferenser. Att ersätta spårningsreferensen med en vanlig handtagsvariabel skulle lämna den resulterande strängarrayen med 10 oinitierade stränghandtag, eftersom endast kopior av stränghandtagen i arrayen skulle ställas in på grund av att de skickas av värde snarare än genom referens.

 

        
       0

         
          
    

     0
 int  main  ()  {  array  <  String  ^>  ^  arr  =  gcnew  array  <  String  ^>  (  10  );  int  i  =  ;  för  varje  (  Sträng  ^%  s  i  arr  )  {  s  =  i  ++  .  ToString  ();  }  returnera  ;  } 

Observera att detta skulle vara olagligt i C#, vilket inte tillåter för varje loop att skicka värden genom referens. Därför skulle en lösning behövas.

Finalizers och automatiska variabler

En annan förändring i C++/CLI är introduktionen av finalizer- syntaxen ! ClassName () , en speciell typ av icke-deterministisk destruktör som körs som en del av sopsamlingsrutinen . C++-destruktorsyntaxen ~ ClassName () finns också för hanterade objekt, och återspeglar bättre den "traditionella" C++-semantiken för deterministisk förstörelse (det vill säga destruktorer som kan anropas med användarkod med delete ).

I det råa .NET-paradigmet åsidosätter den icke-deterministiska destruktionsmodellen den skyddade Finalize -metoden för root Object- klassen , medan den deterministiska modellen implementeras genom IDisposable - gränssnittsmetoden Dispose (som C++/CLI-kompilatorn förvandlar destruktorn till). Objekt från C#- eller VB.NET-kod som åsidosätter Dispose-metoden kan kasseras manuellt i C++/CLI med delete precis som .NET-klasser i C++/CLI kan.


  


      
     

     


      
    
          
 
            
         

        
    
 // C++/CLI  ref  klass  MyClass  {  public  :  MyClass  ();  // konstruktör  ~  MyClass  ();  // (deterministisk) destruktor (implementerad som IDisposable.Dispose())  skyddad  :  !  MyClass  ();  // finalizer (icke-deterministisk destruktor) (implementerad som Finalize())  public  :  static  void  Test  ()  {  MyClass  automatic  ;  // Inte ett handtag, ingen initiering: kompilatorn anropar konstruktorn här  MyClass  ^  user  =  gcnew  MyClass  ();  ta bort  användare  ;  // Kompilatorn anropar automatics destructor när automatic går utanför räckvidden }  }  ; 

Operatör överbelastning

Operatörsöverbelastning fungerar analogt med standard C++. Varje * blir en ^, varje & blir en %, men resten av syntaxen är oförändrad, förutom ett viktigt tillägg: för .NET-klasser är operatöröverbelastning möjlig inte bara för klasserna själva, utan även för referenser till dessa klasser. Denna funktion är nödvändig för att ge en ref-klass den semantik för operatörsöverbelastning som förväntas från .NET ref-klasser. (Omvänt betyder detta också att för .NET framework ref-klasser, är referensoperatörsöverbelastning ofta implicit implementerad i C++/CLI.)

Om du till exempel jämför två distinkta strängreferenser (String^) via operatorn == ger sant när de två strängarna är lika. Operatörens överbelastning är dock statisk. Således kommer casting till Object^ att ta bort den överbelastade semantiken.


   
     
   
   
   
    //effekter av överbelastning av referensoperator  String  ^  s1  =  "abc"  ;  String  ^  s2  =  "ab"  +  "c"  ;  Objekt  ^  o1  =  s1  ;  Objekt  ^  o2  =  s2  ;  s1  ==  s2  ;  // sant  o1  ==  o2  ;  // falskt 

Interoperabilitet

C++/CLI tillåter C++-program att konsumera C#-program i C# DLL:er. Här visar nyckelordet #using kompilatorn där DLL-filen finns för dess kompileringsmetadata. Detta enkla exempel kräver ingen datarangering .

 
  


    
        
     0
 #include  "stdafx.h"  med hjälp av  namnrymden  System  ;  #using "...MyCS.dll"  int  main  (  array  <  System  ::  String  ^>  ^  args  )  {  double  x  =  MyCS  ::  Class1  ::  add  (  40.1  ,  1.9  );  återvända  ;  } 

C#-källkodens innehåll i MyCS.dll.

 

   
           
           
    
 namnutrymme  MyCS  ;  public  class  Class1  {  public  static  double  add  (  double  a  ,  double  b  )  {  return  a  +  b  ;  }  } 

Det här exemplet visar hur strängar sorteras från C++-strängar till strängar som kan anropas från C# och sedan tillbaka till C++-strängar. String rangering kopierar strängens innehåll till former som kan användas i de olika miljöerna.

 
 
 
 
  


  
	   
	    
	    
	    
	    
	    
	 0
 #inkludera  < sträng>   #inkludera  <iostream>  #inkludera  <msclr\marshal_cppstd.h>  #inkludera  "stdafx.h"  med hjälp av  namnutrymme  System  ;  #using "..MyCS.dll"  int  main  ()  {  std  ::  string  s  =  "Jag är katt"  ;  System  ::  String  ^  clrString  =  msclr  ::  interop  ::  marshal_as  <  System  ::  String  ^>  (  s  );  // sträng användbar från C#  System  ::  String  ^  t  =  MyCS  ::  Klass1  ::  process  (  clrString  );  // anropa C#-funktionen  std  ::  sträng  cppString  =  msclr  ::  interop  ::  marshal_as  <  std  ::  sträng  >  (  t  );  // sträng användbar från C++  std  ::  cout  <<  "Hej, C++/C# Interop!"  <<  std  ::  endl  ;  std  ::  cout  <<  cppString  <<  std  ::  endl  ;  återvända  ;  } 

C#-koden är inte på något sätt C++-medveten.

 

   
         
            
    
 namnutrymme  MyCS  ;  public  class  Class1  {  public  static  string  process  (  string  a  )  {  return  a  .  Ersätt  (  "katt"  ,  "hund"  )  +  " med en svans"  ;  }  } 

C++/C#-kompatibilitet tillåter C++ förenklad åtkomst till hela världen av .NET-funktioner.

C++/CX

C++/CX- inriktning mot WinRT , även om den producerar helt ohanterad kod, lånar syntaxen ref och ^ för de referensräknade komponenterna i WinRT, som liknar COM- "objekt".

Vidare läsning

externa länkar