Visual C++ .NET 
C++ v síti Microsoftu 
V článku o Microsoft Visual Studiu .NET v červnovém Chipu jsme slíbili, že se k podporovaným jazykům vrátíme v samostatných článcích. Na prostředí Visual C# .NET došlo hned o měsíc později, nyní se podíváme na Visual C++ .NET. 

Recenze softwarového produktu obvykle začínají srovnáním nové verze s předchozí. V případě Visual C++ .NET by takové srovnání zabralo celý článek, neboť od vydání předchozí verze, Visual C++ 6, uplynuly již čtyři dlouhé roky. Zde proto upozorníme jen na nejdůležitější rozdíly: 
* Visual C++ .NET umožňuje generovat jak programy s neřízeným kódem, tj. s kódem pro prostředí Win32, tak i programy s řízeným kódem pro platformu .NET Framework (NF). Ve skutečnosti jde o jedinou součást Visual Studia .NET, která umí vytvářet "klasický" kód určený pro Win32. 
* Implementace jazyka C++ se přiblížila standardu ISO 14882 - 1998. 
* Visual C++ .NET umožňuje vytvářet řadu nových typů projektů, mimo jiné i webové služby v C++.  

Provedení 
Visual C++ lze získat samostatně pod označením Visual C++ Standard Edition nebo jako součást některého z provedení Visual Studia .NET. (Visual Studio .NET se, jak už víme, v provedení Standard nedodává; jeho nejnižší verze je označena Professional.) 
Visual C++ Standard Edition obsahuje pouze základní vývojové nástroje, tedy integrované vývojové prostředí, překladač, ladicí nástroje a knihovny. Toto provedení je určeno především pro základní výuku programování. Teprve vyšší provedení lze použít k vývoji vážně míněných aplikací. 
Tato recenze vychází ze zkušenosti s prostředím Visual C++, které je součástí provedení Enterprise Architect. Nebudeme se v ní už vracet k věcem, o nichž byla řeč v Chipu 6/02 (Všechno je jinak, str. 104).  

Integrované vývojové prostředí 
Integrované vývojové prostředí (IDE) je v podstatě stejné jako u ostatních jazyků, které jsou součástí nového Visual Studia. Rozdíly najdeme pouze v podružných detailech - například ve srovnání s Visual C# .NET v nabídce nenajdeme příkaz pro generování dokumentace na základě dokumentačních komentářů, liší se i implicitní způsob automatického odsazování atd.  

Nápověda 
Podobně jako ve Visual C# je i zde vedle konvenční nápovědy k dispozici také dynamická nápověda. To znamená, že v jednom z pomocných oken se v průběhu psaní programu neustále zobrazují témata odpovídající právě zapisovanému klíčovému slovu nebo knihovnímu identifikátoru. V případě, že napíšeme jméno třídy nebo prostoru jmen a za ně některý z operátorů ::, . nebo -> (podle toho, co dovolují syntaktická pravidla), nabídne nám IDE v bublině seznam možných složek. Podobně po napsání otevírací závorky za jménem funkce nebo metody nám IDE nabídne seznam typů jejích parametrů. Musíme ale mít na paměti, že všechny tyto mechanismy fungují správně pouze tehdy, má-li prostředí v místě zápisu všechny potřebné informace, tj. předchází-li odpovídající deklarace nebo direktiva using.  

Ladění 
Integrovaný ladicí program Visual Studia .NET samozřejmě podporuje obvyklý komfort: krokování na úrovni zdrojového kódu a disasemblovaného strojního kódu (nikoli však mezijazyka IL), a to se vstupem do procedur i bez něj, kontextově závislé sledování hodnot lokálních proměnných a návratových hodnot funkcí, používání zarážek (breakpoints) vázaných na místo ve zdrojovém kódu, na splnění určité podmínky, na přístup k datům atd. K dispozici jsou i nástroje pro vzdálené ladění, tedy pro ladění distribuovaných aplikací. 
Podobně jako předchozí verze, i Visual Studio .NET podporuje také editaci zdrojového kódu v průběhu ladění (edit and continue). Tato schopnost je užitečná zejména při ladění velice rozsáhlých projektů, neboť po zásahu do zdrojového kódu v průběhu ladění se přeloží jen nezbytná část a ta se připojí k hotovému spustitelnému programu, aniž se přeruší ladění. 
Existují samozřejmě situace, kdy tento mechanismus použít nelze a je nutno přeložit a znovu sestavit celý program. Nicméně i tak tato schopnost znamená významnou úsporu času při ladění. (Editace zdrojového kódu v průběhu ladění je k dispozici pouze ve Visual C++ .NET, ostatní součásti Visual Studia .NET ji bohužel postrádají.)  

Vizuální vývoj 
Na rozdíl od Visual C# .NET a Visual Basic .NET nenabízí Visual C++ .NET možnost vizuálního vývoje aplikací s grafickým uživatelským rozhraním, a to ani pro řízený, ani pro neřízený kód. (Vizuální návrhář pro řízený kód by však měl být součástí připravované nové verze Visual C++.) 
Je jasné, že vytvořit nástroj pro vizuální návrh jen s použitím samotného C++ je poměrně obtížné. Nicméně v případě C++ pro řízený kód jsou k dispozici stejné knihovny jako ve Visual C# .NET nebo ve Visual Basic .NET a postup by se lišil jen v detailech vygenerovaného kódu, takže mi není jasné, proč tato možnost ve Visual C++ chybí.  

Správa projektů 
Podobně jako v předchozí verzi je základní jednotkou vývoje projekt. V předchozí verzi jsme projekty seskupovali do pracovních prostorů (workspace), ve Visual C++ .NET místo nich používáme řešení (solution). Rozdíl je - alespoň z hlediska běžného uživatele - jen formální. Řešení je popsáno v souboru .sln, což je textový soubor se základními informacemi o projektech v něm obsažených. Jednotlivé projekty jsou popsány v souborech .vcproj, a to ve formátu XML. IDE samozřejmě umí bez problémů otevřít i projekty a pracovní prostory z předchozí verze Visual C++. Přibyly nové typy projektů pro řízený kód. 

Programovací jazyky 
Visual C++ .NET v sobě skrývá tři vzájemně blízké, ale přesto rozdílné programovací jazyky: jazyk C podle normy ISO 9899, jazyk C++ podle normy ISO 14882 (tj. pro neřízený kód) a jazyk C++ s rozšířeními pro platformu .NET (řízený kód - tato rozšíření jsou natolik závažná, že stojí za to hovořit o nich jako o samostatném programovacím jazyku).  

Jazyk C 
Implementace jazyka C vyhovuje mezinárodní normě ISO 9899 - 1990 s některými pozdějšími dodatky a s microsoftskými rozšířeními. Neodpovídá ovšem druhé verzi standardu z roku 1999, neboť neimplementuje např. celočíselný typ long long, nelze používat pojmenované inicializátory pro složky struktur a polí, nelze používat složené literály, není k dispozici modifikátor restrict, v příkazu cyklu for nelze deklarovat proměnnou, nelze deklarovat pole s proměnnou délkou atd. Místo klíčového slova inline zavedeného novým standardem jazyka C je třeba použít __inline. 
Najdeme tu ovšem funkce pro práci s "širokými" znaky (tedy s vícebajtovými znaky a s kódem UNICODE). V souladu se standardem jsou umístěny v hlavičkových souborech wctype.h a wchar.h. 
Z rozšíření jsou nepochybně nejvýznamnější strukturované výjimky (SEH - Structured Exception Handling) a možnost používat asembler. Ani jedno ovšem není ničím novým strukturované výjimky se objevily již v prvních microsoftských překladačích jazyka C pro Win32 a klíčové slovo __asm je v microsoftských překladačích ještě daleko starší.  

Jazyk C++ pro neřízený kód 
Implementace jazyka C++ se ve srovnání s předchozí verzí přiblížila standardu ISO 14882 1998. Hlavní novinky v tomto oboru můžeme shrnout do následujících bodů: 
* Visual C++ .NET podporuje vnořené šablony. 
* Visual C++ .NET podporuje přetěžování šablon funkcí. 
* Operátor new vyvolává - alespoň za jistých okolností - v případě neúspěšné alokace výjimku typu bad_alloc. 
* Proměnná deklarovaná v příkazu cyklu for může být lokální v těle cyklu, pokud nastavíme odpovídající přepínač. 
* Tělo funkce nebo konstruktoru může být tvořeno blokem try/catch. 
Zůstala ovšem řada míst, kde se implementace jazyka C++ ve Visual C++ .NET odchyluje od současného standardu. Podrobný rozbor by vydal na menší seriál, a proto se omezíme na pouhý výčet případů, kdy Visual C++ .NET není kompatibilní se standardem. Část z následujících informací je převzata z dokumentace, část pochází z vlastní zkušenosti a část z článků uveřejněných na webových stránkách MSDN. 
* Standard jazyka C++ doporučuje v dodatku B minimální hodnoty omezení pro určité veličiny; implementace by například měla povolovat alespoň 256 úrovní vnoření direktiv #if. Překladač Visual C++ 
* .NET některé z doporučených hodnot nerespektuje. Jde např. o počet úrovní vnoření složených příkazů, počet parametrů v definici a v použití makra, počet parametrů v deklaraci šablony atd. 
* Visual C++ .NET nepodporuje klíčové slovo asm. Místo něj se podobně jako v předchozích verzích - používá klíčové slovo __asm, za nímž následují příkazy asembleru ve složených závorkách. 
* Visual C++ .NET sice podporuje vnořené šablony, ale některá správná použití nedokáže přeložit. Mně se např. nepodařilo přeložit učebnicový příklad třídy obsahující šablonu operátoru přetypování. (Překladač hlásil chyby při implicitním použití tohoto operátoru.) 
* Lze najít příklady, kdy překladač při vytváření instance šablony nesprávně určí externí jména použitá v její deklaraci. 
* Překladač nezná klíčová slova and, not, xor_eq a další, jimiž lze nahradit operátory &&, ~, ^= atd. (Pokud chceme tyto náhrady používat, musíme použít hlavičkový soubor iso646.h, což je v rozporu s normou.) 
* Visual C++ .NET implementuje vyhledávání přetížených operátorů v závislosti na parametrech (tzv. Koenigovo vyhledávání), ovšem pouze v případě, že byl použit operátorový zápis (např. a + b). 
* V případě zápisu operátorové funkce (např. a.operator+(b)), se Koenigovo vyhledávání nepoužije, stejně jako při volání "obyčejných" (neoperátorových) funkcí a metod. 
Visual C++ .NET umožňuje deklarovat v podmínce příkazu if proměnnou, ale nesprávně interpretuje její oblast platnosti. 
* Visual C++ .NET neimplementuje klíčové slovo export pro šablony. (Pokud vím, neimplementuje ho žádný současný komerční překladač, a to přesto, že je součástí standardu již čtyři roky. Jde zřejmě o jednu z nejproblematičtějších konstrukcí ve standardu C++.) 
* Třídu, kterou deklarujeme jako složku šablony třídy, musíme v jejím těle také definovat. Visual C++ .NET nedovoluje uvést v těle šablony třídy jen deklaraci třídy a definici zapsat mimo tělo. 
* Visual C++ .NET nepodporuje parciální specializaci šablon tříd. 
* Visual C++ .NET nepodporuje parciální řazení šablon funkcí. 
* Visual C++ .NET sice umožňuje zapsat za hlavičku funkce nebo metody specifikaci typů výjimek, které se z ní mohou rozšířit, avšak respektuje pouze specifikaci throw() s prázdným seznamem. (To platilo i v předchozí verzi.) 
* Funkce uncaught_exception() vrací vždy false. 
* Visual C++ .NET nepodporuje univerzální jména znaků zapisovaná pomocí \uXXXX, nebo \UXXXXXXXX, tj. v kódování UNICODE, a to ani ve znakových konstantách, ani v identifikátorech. 
* Visual C++ nedovoluje prázdný inicializátor struktur a polí.  

Rozšíření C++ pro řízený kód 
Tvůrci překladače C++ pro řízený kód ve Visual Studiu .NET stáli před nelehkým úkolem: Přizpůsobit jazyk C++ požadavkům prostředí NF tak, aby programy v C++ mohly využívat komponent napsaných v jiných programovacích jazycích - a naopak, abychom mohli v C++ psát komponenty použitelné v jakémkoli jiném jazyku v tomto prostředí. To znamená, že datové typy musí např. mít společného předka, třídu System::Object, musí být založeny na jednoduché dědičnosti, musí podporovat ukládání metadat do přeložených souborů atd. Přesněji řečeno, musí mj. vyhovovat požadavkům společného typového systému (CTS) prostředí NF. 
Výsledkem těchto úprav jsou rozšíření jazyka C++ pro řízený kód, anglicky označovaná Managed Extensions. Podrobný výklad o nich by byl dalším námětem na seriál, neboť jen jejich specifikace doplněná stručnými příklady zabírá přes sto stran formátu A4. Proto se omezíme alespoň na základní informace. 
Na jazyk C++ pro řízený kód se můžeme dívat jako na C# zapsané pomocí vyjadřovacích prostředků obvyklých v C++. Posuďte sami: 
V programech pro NF musíme mít k dispozici nejen datové typy z knihoven tohoto prostředí (BCL, knihovny pro "okna", pro práci s databázemi atd.), ale i veřejně přístupné datové typy z ostatních programů a knihoven pro NF. Aby s nimi bylo možné pracovat, musí si překladač umět přečíst jejich metadata. K tomu slouží direktiva #using, jež umožňuje použít dynamické knihovny z NF podobně jako hlavičkové soubory. Například téměř všechny programy pro NF začínají direktivou 

#using <mscorlib.dll> 

Standardní knihovny jsou v prostředí NF rozděleny do velkého množství hierarchicky uspořádaných prostorů jmen. Jim odpovídají knihovny, na které lze v direktivě #using odkazovat zápisem složeným z jednotlivých vnořených prostorů jmen spojených tečkami. Například nástroje pro tvorbu grafického uživatelského rozhraní, které najdeme v prostoru jmen System::Windows::Forms, zpřístupníme zápisem 

#using <System.Windows.Forms.dll> using namespace System::Windows::Forms; 

Třídy v prostředí NF vyhovující specifikaci CTS mají společného předka, třídu System::Object. Jejich instance jsou rušeny automatickou správou paměti (garbage collector), zatímco třídy v C++ nemusí ležet v žádné dědické hierarchii a jejich instance musí programátor rušit sám. Abychom mohli v programech pro řízený kód používat jak třídy vyhovující CTS, tak i "klasické" třídy z C++, zavádí Visual C++ .NET modifikátor __gc. Třídy s tímto modifikátorem odpovídají požadavkům CTS. Takováto třída smí mít jen jediného předka, a to opět třídu s modifikátorem __gc; pokud u ní předka nespecifikujeme, doplní si překladač třídu System::Object. Její instance musíme vytvářet dynamicky, pomocí operátoru __gc new, a platí pro ně ještě některá další omezení - například nesmějí mít kopírovací konstruktor. Na druhé straně mohou mít např. statický konstruktor, který se volá při zavedení třídy do paměti a slouží k inicializaci statických datových složek. (Jde o analogii statického konstruktoru z C# nebo statického inicializátoru z Javy.) 
K označení "klasických" tříd lze (a za jistých okolností je třeba) použít modifikátor __nogc. Vedle toho můžeme deklarovat třídy s modifikátorem __value. Jde o analogii struktur z C#, tedy o třídy, jejichž instance se budou vytvářet v zásobníku a které přitom budou kompatibilní s CTS. 
Třídy s modifikátorem __gc můžeme také deklarovat jako "zapečetěné" (sealed classes), tj. jako třídy, od nichž nelze odvodit potomka; v jejich deklaraci lze použít i modifikátor __abstract, i když je zbytečný. 
K deklaraci třídy s modifikátorem __gc lze připojit specifikaci přístupových práv. Tyto třídy mohou vedle datových složek, metod, konstruktorů a destruktoru obsahovat také vlastnosti, události a operátory přetížené jako statické metody (tedy podle pravidel jazyka C#; tyto operátory ovšem nelze v C++ používat v infixovém zápisu, tedy jako operátory přetížené podle pravidel C++). 
Novinkou jsou také tzv. delegáty, což jsou vlastně objektově zapouzdřené ukazatele na metody tříd s modifikátorem __gc. Nejde ovšem o ukazatele v žádném ze smyslů používaných v C++, neboť delegát obsahuje buď adresu nestatické metody spolu s adresou objektu, pro nějž ji chceme volat, nebo adresu statické metody. Delegáty typu void mohou obsahovat více ukazatelů, což je výhodné při zpracování událostí. 
Při zpracování událostí se používá dnes už klasický návrhový vzor "vydavatel-předplatitel" (publisher-subscriber), známý mj. z Javy. 
K deklaracím datových typů, metod, parametrů atd. lze připojit tzv. atributy, deklarativní informace, které se uloží v podobě metadat do přeloženého souboru.  

Knihovny 
Součástí instalace je samozřejmě i řada knihoven. Vedle standardní knihovny jazyka C je nepominutelnou součástí každé implementace jazyka C++ standardní šablonová knihovna (STL). Vzhledem k tomu, že se současná implementace jazyka C++ ve Visual C++ .NET značně přiblížila standardu, přiblížila se standardu i implementace STL (to se týká mj. implementace alokátoru). Uživatele knihovny se dotknou zejména změny jmen tříd některých reverzních iterátorů. Problémy může způsobit i skutečnost, že některé iterátory - např. pro třídu string - již nejsou implementovány jako ukazatele. Autorem současné verze 3.10, stejně jako předchozích verzí microsoftské implementace knihovny STL, je P. J. Plauger. 
Vedle toho zde najdeme tradiční knihovnu MFC verze 7.0. Kromě nástrojů pro programování grafického uživatelského rozhraní v ní najdeme prostředky pro přístup k databázím prostřednictvím DAO a ODBC, pro síťové programování založené na Windows Sockets a pro programování pro internet. Nové třídy zapouzdřují také nové možnosti, které přinesly Windows 2000 a Windows XP. Pro vytváření komponent COM je k dispozici šablonová knihovna ATL verze 7. V aplikacích pro řízený kód můžeme samozřejmě používat knihovnu BCL a další knihovny z prostředí NF.  

Požadavky 
Nároky Visual C++ .NET jsou podobné jako u celého Visual Studia .NET. Minimum představuje PC vybavený procesorem Intel Pentium II/450 MHz nebo kompatibilním, grafickou kartou SVGA s rozlišením 600 x 800 pixelů a s dalším běžným příslušenstvím. Nezbytný je operační systém Windows NT 4 Workstation, Windows NT 4 Server, Windows 2000 Professional, Windows 2000 Server nebo Windows XP Professional. Minimální nároky na operační paměť se liší podle operačního systému, a to od 64 MB RAM pro Windows NT 4 Workstation po 192 MB pro Windows 2000 Server. Plná instalace zabere 600 MB na systémovém disku a 2 GB na instalačním disku.  

Dojem 
Celkový dojem je těžké shrnout v jedné větě. Je to impozantní software, ovšem ne zcela dokončený. Jeho nespornou výhodou je úzká návaznost na operační systém Windows a na platformu NF, stejně jako snadná spolupráce s ostatními vývojovými nástroji Visual Studia .NET. 
Dá se však i leccos vytknout: chybí nástroje pro vizuální vývoj aplikací s grafickým uživatelským rozhraním a také nároky tohoto produktu jsou dosti kolosální. Rovněž shoda jazyka C++ se standardem (pokud jde o neřízený kód) je poněkud menší než u jiných konkurenčních produktů, což může ovlivnit přenositelnost programů. 

Miroslav Virius