C++/CLI
Paradigm | Strukturerad , imperativ , objektorienterad |
---|---|
Familj | C |
Designad av | Microsoft |
Utvecklare | Microsoft |
Dök först upp | 2005 |
Plattform | Gemensam språkinfrastruktur |
Hemsida | |
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
- Sutter, Herb (23 november 2003). "C++/CLI nyckelord: Under huven" . Herb Sutters blogg . Microsoft . Arkiverad från originalet den 9 november 2007.
- Sutter, Herb (24 februari 2006). "En designgrund för C++/CLI" (PDF) . Självpublicerad .
- Stroustrup, Bjarne (23 juli 2021). "Vad tycker du om C++/CLI?" . Bjarne Stroustrups FAQ . Självpublicerad .
- Lippman, Stanley . "Ren C++: Hej, C++/CLI" . MSDN Magazine . Microsoft . 21 (3). Arkiverad från originalet den 5 februari 2008.
- Lippman, Stanley (5 augusti 2004). "Varför C++/CLI stöder både mallar för CLI-typer och CLI Generic Mechanism" . Stan Lippmans blogg . Microsoft . Arkiverad från originalet den 7 oktober 2007.