C++ | |
---|---|
Semantică | multi- paradigma : orientat pe obiecte , generic , procedural , metaprogramare |
Clasa de limba | limbaj de programare orientat pe obiecte , limbaj de programare multi -paradigma , limbaj de programare procedural , limbaj de programare functional ,de programare generic , limbaj de programare , limbaj cu forma libera [d] si limbaj de programare compilat |
Tipul de execuție | compilate |
Aparut in | 1983 |
Autor | Stroustrup, Bjorn |
Extensie de fișier | .cc, .cpp, .cxx, .c, .c++, .h, .hpp, .hh, .hxxsau.h++ |
Eliberare | |
Tip sistem | static |
Implementări majore | GNU C++ , Microsoft Visual C++ , compilator Intel C++ , compilator Open64 C++ , Clang , Comeau C/C++ , Embarcadero C++ Builder , compilator Watcom C++ , Digital Mars C++, compilator Oracle Solaris Studio C++, Turbo C++ |
Dialectele | ISO/IEC 14882 C++ |
A fost influențat | C , Simula , Algol 68 , Clu , ML și Ada |
Site-ul web | isocpp.org _ |
Fișiere media la Wikimedia Commons |
C ++ (pronunțat c-plus-plus [2] [3] ) este un limbaj de programare compilat , tip static , de uz general
Suportă paradigme de programare precum programarea procedurală , programarea orientată pe obiecte , programarea generică . Limbajul are o bibliotecă standard bogată care include containere și algoritmi obișnuiți , I/O, expresii regulate, suport pentru multithreading și multe altele. C++ combină caracteristicile atât ale limbajelor de nivel înalt, cât și ale limbajelor de nivel scăzut [4] [5] . În comparație cu predecesorul său - limbajul C - cea mai mare atenție este acordată suportului pentru programarea orientată pe obiecte și generică [5] .
C++ este utilizat pe scară largă pentru dezvoltarea de software, fiind unul dintre cele mai populare limbaje de programare [opinii 1] [opinii 2] . Domeniul său de aplicare include crearea de sisteme de operare , o varietate de programe de aplicații, drivere de dispozitiv , aplicații pentru sisteme încorporate, servere de înaltă performanță și jocuri pe calculator. Există multe implementări ale limbajului C++, atât gratuite, cât și comerciale, și pentru diverse platforme. De exemplu, pe platforma x86 , acestea sunt GCC , Visual C++ , Intel C++ Compiler , Embarcadero (Borland) C++ Builder și altele. C++ a avut un impact uriaș asupra altor limbaje de programare, în special Java și C# .
Sintaxa C++ este moștenită din limbajul C. Unul dintre principiile de proiectare originale a fost menținerea compatibilității cu C. Cu toate acestea, C++ nu este strict un superset al lui C; Setul de programe care pot fi traduse la fel de bine de către compilatoarele C și C++ este destul de mare, dar nu include toate programele C posibile .
Stadiul istoric al dezvoltării [6] | An |
---|---|
limbajul BCPL | 1966 |
Limbajul B (dezvoltare originală de Thompson sub UNIX ) | 1969 |
limbajul C | 1972 |
C cu clase | 1980 |
C84 | 1984 |
Cfront (ediția E) | 1984 |
cfront (versiunea 1.0) | 1985 |
Moștenire multiplă/virtuală | 1988 |
Programare generică ( şabloane ) | 1991 |
ANSI C++ / ISO-C++ | 1996 |
ISO/IEC 14882:1998 | 1998 |
ISO/IEC 14882:2003 | 2003 |
C++/CLI | 2005 |
TR1 | 2005 |
C++11 | 2011 |
C++14 | 2014 |
C++17 | 2017 |
C++20 | 2020 |
Limbajul a apărut la începutul anilor 1980 , când angajatul Bell Labs , Björn Stroustrup , a venit cu o serie de îmbunătățiri ale limbajului C pentru propriile nevoi [7] . Când Stroustrup a început să lucreze la Bell Labs, la sfârșitul anilor 1970 , cu privire la problemele legate de teoria cozilor de așteptare (așa cum se aplică modelării apelurilor telefonice), a descoperit că încercările de a folosi limbaje de modelare existente la acea vreme erau ineficiente și utilizarea limbajelor de mașină foarte eficiente. a fost prea dificil pentru că pentru expresivitatea lor limitată. De exemplu, limbajul Simula are caracteristici care ar fi foarte utile pentru dezvoltarea de software de mari dimensiuni, dar este prea lent, iar limbajul BCPL este suficient de rapid, dar prea aproape de limbajele de nivel scăzut și nu este potrivit pentru dezvoltarea de software de mari dimensiuni.
Reamintind experiența disertației sale, Stroustrup a decis să completeze limbajul C (succesorul BCPL) cu capabilitățile disponibile în limbajul Simula. Limbajul C, fiind limbajul de bază al sistemului UNIX pe care rulau computerele Bell, este rapid, bogat în funcții și portabil. Stroustrup i-a adăugat capacitatea de a lucra cu clase și obiecte. Ca urmare, problemele practice de modelare s-au dovedit a fi accesibile atât în ceea ce privește timpul de dezvoltare (datorită utilizării claselor de tip Simula), cât și în ceea ce privește timpul de calcul (datorită vitezei lui C). Primele completări la C au fost clasele (cu încapsulare ), moștenirea claselor, verificarea strictă a tipului, funcțiile în linie și argumentele implicite . Versiunile timpurii ale limbii, numite inițial „C cu clase”, au fost disponibile încă din anii 1980 .
În timp ce dezvolta C cu clase , Stroustrup a scris programul cfront , un compilator care reprocesează codul sursă C cu clase în cod sursă simplu C. Acest lucru ne-a permis să lucrăm la un nou limbaj și să-l folosim în practică, folosind infrastructura deja disponibilă în UNIX pentru dezvoltare în C. Un nou limbaj, neașteptat pentru autor, a câștigat o mare popularitate în rândul colegilor și în curând Stroustrup nu l-a mai putut susține personal, răspunzând la mii de întrebări.
Până în 1983, limbii au fost adăugate noi caracteristici, cum ar fi funcții virtuale, supraîncărcare de funcții și operatori, referințe, constante, controlul utilizatorului asupra gestionării memoriei libere, verificare îmbunătățită a tipului și un nou stil de comentariu ( //). Limbajul rezultat nu mai este doar o versiune augmentată a clasicului C și a fost redenumit din C cu clase în „C++”. Prima sa lansare comercială a avut loc în octombrie 1985 .
Înainte de începerea standardizării oficiale, limbajul a fost dezvoltat în principal de Stroustrup, ca răspuns la solicitările din partea comunității de programare. Funcția descrierilor în limbaj standard a fost îndeplinită de lucrările tipărite ale lui Stroustrup pe C++ (o descriere a limbajului, un manual de referință și așa mai departe). Abia în 1998 a fost ratificat standardul internațional pentru limbajul C++: ISO/IEC 14882:1998 „Standard pentru limbajul de programare C++”; după adoptarea corecțiilor tehnice la standard în 2003, următoarea versiune a acestui standard este ISO/IEC 14882:2003 [8] .
În 1985, a apărut prima ediție a Limbului de programare C++ , oferind prima descriere a limbajului, care a fost extrem de importantă din cauza lipsei unui standard oficial. În 1989, a fost lansată versiunea C++ 2.0. Noile sale caracteristici includ moștenirea multiplă, clase abstracte, funcții membre statice, funcții constante și membri protejați. În 1990, a fost publicat „Ghidul de referință comentat pentru C++”, care a devenit ulterior baza standardului. Actualizările recente au inclus șabloane, excepții, spații de nume, noi modele și tipul boolean. Biblioteca de șabloane standard (STL) dezvoltată de Alexander Stepanov și Meng Li a fost aleasă ca bază pentru stocarea și accesarea algoritmilor generici .
Biblioteca standard C++ a evoluat și ea odată cu ea. Prima adăugare la biblioteca standard C++ a fost fluxurile I/O, oferind un mijloc de a înlocui C printfși scanf. Mai târziu, cea mai semnificativă dezvoltare a bibliotecii standard a fost includerea Bibliotecii standard de șabloane .
C++ continuă să evolueze pentru a satisface cerințele moderne. Unul dintre grupurile care dezvoltă limbajul C++ și trimit propuneri de îmbunătățire a acestuia către comitetul de standardizare C++ este Boost , care este angajat, printre altele, în îmbunătățirea capacităților limbajului prin adăugarea de caracteristici de metaprogramare la acesta .
Nimeni nu deține drepturile asupra limbajului C++, este gratuit. Cu toate acestea, documentul standard de limbă în sine (cu excepția proiectelor) nu este disponibil gratuit [10] . Ca parte a procesului de standardizare, ISO produce mai multe tipuri de publicații. În special, rapoartele tehnice și specificațiile tehnice sunt publicate atunci când „viitorul este în vedere, dar nu există posibilitatea imediată de acord pentru publicarea unui standard internațional”. Până în 2011, au fost publicate trei rapoarte tehnice despre C++: TR 19768: 2007 (cunoscut și ca Raport tehnic C++ 1) pentru extensiile de bibliotecă integrate în principal în C++11, TR 29124: 2010 pentru funcții matematice speciale și TR 24733: 2011 pentru aritmetică zecimală în virgulă mobilă. Specificație tehnică DTS 18822:. 2014 (prin sistem de fișiere) a fost aprobat la începutul anului 2015, iar restul caietului de sarcini sunt în curs de elaborare și așteaptă aprobare [11] .
În martie 2016, grupul de lucru WG21 C++ a fost creat în Rusia . Grupul a fost organizat pentru a colecta propuneri pentru standardul C++, a le înainta comitetului și a le apăra în cadrul reuniunilor generale ale Organizației Internaționale pentru Standardizare (ISO) [12] .
Numele de limbă rezultat provine de la operatorul de increment postfix unar C ++(incrementând valoarea unei variabile cu unu). Numele C+ nu a fost folosit deoarece este o eroare de sintaxă în C și, în plus, numele a fost preluat de un alt limbaj. De asemenea, limbajul nu a fost numit D pentru că „ este o extensie a lui C și nu încearcă să rezolve problemele prin eliminarea elementelor C ” [7] .
În The Design and Evolution of C++ [13] , Bjorn Stroustrup descrie principiile pe care le-a urmat atunci când a proiectat C++. Aceste principii explică de ce C++ este așa. Unii dintre ei:
Standardul C++ constă din două părți principale: o descriere a limbajului de bază și o descriere a bibliotecii standard.
La început, limbajul s-a dezvoltat în afara cadrului formal, în mod spontan, în funcție de sarcinile cu care i s-a confruntat. Dezvoltarea limbajului a fost însoțită de dezvoltarea compilatorului cfront cross . Inovațiile în limbaj s-au reflectat în schimbarea numărului de versiune a compilatorului încrucișat. Aceste numere de versiuni cross-compiler s-au extins la limbajul în sine, dar versiunile C++ nu sunt discutate în prezent. Abia în 1998 limba a devenit standardizată.
Un spațiu de nume fără nume este un caz special. Toate numele descrise în acesta sunt disponibile numai în unitatea de traducere curentă și au legături locale. Spațiul de nume stdconține bibliotecile standard C++.
Următoarele tipuri încorporate sunt disponibile în C++. Tipurile C++ sunt aproape identice cu tipurile de date C :
Operatorii de comparație returnează tipul bool. Expresiile dintre paranteze după if, while sunt convertite la tipul bool[14] .
Limbajul a introdus conceptul de referințe, iar din standardul C++11 , rvalues - referințe și referințe de redirecționare . (vezi Link (C++) )
C++ adaugă caracteristici orientate pe obiecte la C. Introduce clase care oferă cele mai importante trei proprietăți ale POO : încapsulare , moștenire și polimorfism .
În standardul C++, o clasă este un tip definit de utilizator, declarat folosind unul dintre cuvintele cheie sau class, structo unionstructură este o clasă definită de struct, iar uniunea este o clasă definită de union. În funcție de cuvântul cheie utilizat, unele proprietăți ale clasei în sine se modifică. De exemplu, într-o clasă declarată cu struct, membrii fără un modificator de acces atribuit manual vor fi implicit publici și nu privat.
În corpul unei definiții de clasă, puteți specifica atât declarațiile de funcție, cât și definiția lor. În acest din urmă caz, funcția este inline ( inline). Funcțiile membre nestatice pot avea constși calificatori volatile, precum și un calificator de referință ( &sau &&).
C++ acceptă moștenirea multiplă . Clasele de bază (clasele strămoși) sunt specificate în capul declarației de clasă, eventual cu specificatori de acces. Moștenirea din fiecare clasă poate fi publică, protejată sau privată:
Mod de acces/moștenire pentru membrii clasei de bază | membru privat | membru protejat | membru public |
---|---|---|---|
moștenire privată | nu e disponibil | privat | privat |
protejat-moştenire | nu e disponibil | protejat | protejat |
mostenirea publica | nu e disponibil | protejat | public |
În mod implicit, clasa de bază este moștenită ca privată.
Ca urmare a moștenirii, clasa copil primește toate câmpurile claselor strămoși și toate metodele acestora; putem spune că fiecare instanță a clasei descendente conține o subinstanță a fiecăreia dintre clasele strămoși. Dacă o clasă strămoșească este moștenită de mai multe ori (acest lucru este posibil dacă este strămoșul mai multor clase de bază ale clasei care este creată), atunci instanțe ale clasei descendente vor include cât mai multe subinstanțe ale acestei clase strămoși. Pentru a evita acest efect dacă nu se dorește, C++ acceptă conceptul de moștenire virtuală . La moștenire, clasa de bază poate fi declarată virtuală; pentru toate aparițiile virtuale ale clasei strămoși în arborele de moștenire al clasei descendente, este creată o singură subinstanță în descendent.
C++ acceptă polimorfismul dinamic și polimorfismul parametric .
Polimorfismul parametric este reprezentat de:
Polimorfismul dinamic este implementat folosind metode virtuale și o ierarhie de moștenire. În C++, un tip este polimorf dacă are cel puțin o metodă virtuală. Exemplu de ierarhie:
Figura de clasă { public : gol virtual Draw () = 0 ; // metoda virtuală pură virtuală ~ Figura ( ); // dacă există cel puțin o metodă virtuală, destructorul trebuie făcut virtual }; Class Square : figură publică { public : void Draw () suprascrie ; }; clasa Cercul : figură publică { public : void Draw () suprascrie ; };Aici clasa Figure este abstractă (și chiar clasa interfață ), deoarece metoda Draw nu este definită. Obiectele acestei clase nu pot fi create, dar pot fi folosite referințe sau pointeri cu tipul Figure. Alegerea implementării metodei Draw se va face în timpul rulării pe baza tipului real al obiectului.
Încapsularea în C++ este implementată prin specificarea nivelului de acces la membrii clasei: aceștia sunt publici (publici, public), protejați ( protected) și privați (privati, private). În C++, structurile diferă formal de clase doar prin aceea că implicit nivelul de acces la membrii clasei și tipul de moștenire pentru o structură sunt publice, în timp ce pentru o clasă sunt private.
Acces | privat | protejat | public |
---|---|---|---|
Clasa în sine | da | da | da |
Prieteni | da | da | da |
moștenitori | Nu | da | da |
Din afara | Nu | Nu | da |
Verificarea accesului are loc în timpul compilării, încercarea de a accesa un membru al clasei inaccesibil va cauza o eroare de compilare.
PrieteniFuncțiile prieten sunt funcții care nu sunt funcții membre și totuși au acces la membrii protejați și privați ai clasei. Ele trebuie să fie declarate în corpul clasei ca friend. De exemplu:
class Matrix { prieten Matrix Multiply ( Matrix m1 , Matrix m2 ); };Aici, funcția Multiplypoate accesa orice câmpuri și funcții membre ale Matrix.
Atât întreaga clasă, cât și o funcție membră a clasei pot fi declarate prietene. Patru restricții importante privind relațiile de prieteni în C++ sunt:
În general, această regulă poate fi formulată astfel: „Relația de prietenie există doar între acele clase (clasa și funcție) pentru care este declarată explicit în cod, și acționează numai în direcția în care este declarată”.
O clasă implicită poate avea șase funcții speciale: constructor implicit, constructor de copiere, constructor de mutare, destructor, operator de atribuire de copiere, operator de atribuire de mutare. De asemenea, este posibil să le definiți în mod explicit pe toate (vezi regula celor trei ).
class Array { public : Matrice ( ) = implicit // compilatorul va crea un constructor implicit al Array în sine ( size_t _len ) : len ( _len ) { val = new double [ _len ]; } Array ( const Array & a ) = delete ; // constructorul de copiere a eliminat explicit Array ( Array && a ); // mută constructorul ~ Array () { şterge [] val ; } Array & operator = ( const Array & rhs ); // copiere operator de atribuire Array & operator = ( Array && rhs ); // mutați operatorul de atribuire dublu și operatorul []( size_t i ) { return val [ i ]; } const double & operator []( size_t i ) const { return val [ i ]; } protejat : std :: size_t len = 0 ; // inițializare câmp double * val { nullptr }; };Constructorul este chemat pentru a inițializa obiectul (de tipul corespunzător) atunci când este creat, iar destructorul este chemat pentru a distruge obiectul. O clasă poate avea mai mulți constructori, dar un destructor poate avea doar unul. Constructorii din C++ nu pot fi declarați virtuali, dar destructorii pot, și sunt de obicei declarați pentru toate tipurile polimorfe, pentru a se asigura că un obiect referit sau accesibil prin pointer este distrus corespunzător, indiferent de tipul referinței sau pointerului. Dacă cel puțin una dintre clasele de bază are un destructor virtual, destructorul clasei copil devine automat virtual.
Șabloanele vă permit să generați funcții și clase care sunt parametrizate cu un anumit tip sau valoare. De exemplu, clasa anterioară ar putea implementa o matrice pentru orice tip de date:
template < typenameT > _ class Array { ... T & operator []( size_t i ) { return val [ i ]; } protejat : std :: size_t len { 0 }; // inițializare câmp T * val { nullptr }; };Biblioteca standard C++ include un set de instrumente care ar trebui să fie disponibile pentru orice implementare a limbajului pentru a oferi programatorilor o utilizare confortabilă a caracteristicilor limbajului și pentru a oferi o bază pentru dezvoltarea atât a unei game largi de aplicații, cât și a bibliotecilor specializate. Biblioteca standard C++ include o parte din biblioteca standard C. Standardul C++ conține o referință normativă la standardul C din 1990 și nu definește în mod independent acele funcții standard ale bibliotecii care sunt împrumutate din biblioteca standard C.
#includeAccesul la capabilitățile bibliotecii standard C++ este asigurat prin includerea fișierelor de antet standard adecvate în program (prin directiva ). În total, 79 de astfel de fișiere sunt definite în standardul C++11. Facilitățile standard de bibliotecă sunt declarate ca parte a spațiului de nume std. Fișierele antet ale căror nume se potrivesc cu modelul „cX”, unde X este numele fișierului antet al Bibliotecii standard C fără extensie (cstdlib, cstring, cstdio etc.), conțin declarații corespunzătoare acelei părți a bibliotecii standard C. funcțiile standard ale bibliotecii se găsesc și în namespace std.
Biblioteca standard include următoarele secțiuni:
Containerele, șirurile de caractere, algoritmii, iteratoarele și utilitățile de bază, cu excepția împrumuturilor din biblioteca C, sunt numite colectiv STL (Standard Template Library - bibliotecă standard de șabloane). Inițial, această bibliotecă a fost un produs separat și abrevierea sa a fost descifrată diferit, dar apoi a intrat în biblioteca standard C++ ca element integral. Denumirea reflectă faptul că mecanismele de programare generalizate (șabloane C++ - șablon) sunt folosite pentru a implementa instrumente de uz general (containere, șiruri de caractere, algoritmi). Scrierile lui Stroustrup detaliază motivele pentru care s-a făcut această alegere. Principalele sunt universalitatea mai mare a soluției alese (containerele șablon, spre deosebire de containerele de obiecte, pot fi utilizate cu ușurință pentru tipurile non-obiecte și nu necesită un strămoș comun pentru tipurile de elemente) și eficiența sa tehnică (de regulă, container șablon operațiunile nu necesită apeluri de funcții virtuale și pot fi ușor încorporate (inline), ceea ce oferă în cele din urmă un câștig de performanță).
Începând cu standardul C++11, au fost adăugate următoarele caracteristici:
STL, înainte de a fi inclus în standardul C++, a fost o dezvoltare terță parte, mai întâi de către HP și apoi de către SGI . Standardul de limbă nu îl numește „STL”, deoarece această bibliotecă a devenit parte integrantă a limbii, totuși mulți oameni încă folosesc acest nume pentru a o deosebi de restul bibliotecii standard (fluxuri I/O ( iostream ), subsecțiunea C si altele).
Un proiect numit STLport [15] bazat pe SGI STL menține la zi clasele STL, IOstream și string. Câteva alte proiecte dezvoltă, de asemenea, utilizări private ale bibliotecii standard.
Alegerea lui C ca bază pentru crearea unui nou limbaj de programare se explică prin faptul că limbajul C:
În ciuda unui număr de deficiențe binecunoscute ale limbajului C, Stroustrup a ales să-l folosească ca bază pentru că „C are problemele sale, dar un limbaj conceput de la zero le-ar avea, iar noi cunoaștem problemele lui C”. În plus, acest lucru ne-a permis să obținem rapid un prototip de compilator ( cfront ) care a tradus doar elementele de sintaxă adăugate în limbajul C original.
Pe măsură ce C++ s-a dezvoltat, au fost incluse și alte caracteristici care suprascriu capacitățile constructelor C și problema renunțării la compatibilitatea limbajului prin eliminarea constructelor depreciate a fost ridicată în mod repetat. Cu toate acestea, compatibilitatea a fost menținută din următoarele motive:
Noile caracteristici C++ includ declarații de expresie, conversii ale tipului de funcție, operatori newși delete, tip bool, referințe, constanță extinsă, funcții inline, argumente implicite, suprascrieri, spații de nume, clase (inclusiv toate caracteristicile legate de clasă, cum ar fi moștenirea, funcțiile membre, funcțiile virtuale, abstractele). clase și constructori ), înlocuiri de operator, șabloane, operator ::, gestionarea excepțiilor, identificare dinamică și multe altele. Limbajul C++ este, de asemenea, în multe cazuri, mai strict în ceea ce privește verificarea tipului decât C.
C++ a introdus comentarii cu două bare oblice ( //) care erau în predecesorul lui C, BCPL .
constUnele caracteristici ale C++ au fost ulterior portate în C, cum ar fi cuvintele cheie și , inlinedeclarațiile de buclă forși comentariile în stil C++ ( //). Implementările ulterioare ale C au introdus și caracteristici care nu se găsesc în C++, cum ar fi macrocomenzi va_argși gestionarea îmbunătățită a parametrilor matricei.
În timp ce majoritatea codului C va fi valabil și pentru C++, C++ nu este un superset al C și nu îl include. Există, de asemenea, un cod care este adevărat pentru C, dar nu pentru C++. Acest lucru îl deosebește de Obiectivul C , o altă îmbunătățire C pentru OOP , care este doar un superset de C.
Există și alte diferențe. De exemplu, C++ nu permite apelarea unei funcții main()în interiorul unui program, în timp ce în C este legală. De asemenea, C++ este mai strict în unele privințe; de exemplu, nu permite turnarea implicită între tipuri de pointer nelegate și nu permite funcții care nu sunt încă declarate.
Mai mult, codul care este valabil pentru ambele limbi poate produce rezultate diferite în funcție de compilatorul în care limbă este tradus. De exemplu, pe majoritatea platformelor, următorul program afișează „C” dacă este compilat de un compilator C și „C++” dacă este compilat de un compilator C++. Acest lucru se datorează faptului că constantele de caractere în C (de exemplu, 'a') sunt de tip int, dar în C++ sunt de tip char, iar dimensiunile acestor tipuri de obicei diferă.
#include <stdio.h> int main () { printf ( "%s \n " , ( dimensiunea ( 'a ' ) == dimensiunea ( caracter )) ? "C++" : "C" ); returnează 0 ; }După cum notează Stroustrup, „Cu cât cunoașteți mai bine C, cu atât vă va fi mai dificil să evitați programarea C++ în stilul C, pierzând în același timp beneficiile potențiale ale C++”. În acest scop, el face următorul set de recomandări pentru programatorii C pentru a profita din plin de C++:
Actualul standard lingvistic ISO/IEC 14882:2017 a fost publicat în decembrie 2017 . Este denumit în mod neoficial C++17 . Următoarea versiune a standardului, programată pentru 2020, are denumirea neoficială C++20 .
Potrivit autorului limbii, Björn Stroustrup [19] [20] [21] , vorbind despre dezvoltarea ulterioară și perspectivele limbii, se pot distinge următoarele:
Acesta este un exemplu de program Bună, lume! , care imprimă un mesaj pe consolă utilizând biblioteca standard și iese.
#include <iostream> folosind namespace std ; int main () { cout << "Bună, lume!" << endl ; returnează 0 ; }C++ modern vă permite să rezolvați probleme mai complexe într-un mod simplu. Acest exemplu demonstrează, printre altele, utilizarea containerelor Standard Template Library ( STL ).
#include <iostream> // pentru a folosi std::cout #include <vector> // conține o matrice dinamică #include <map> // conține tipul de date din dicționar #include <șir> int main () { // Importă toate declarațiile din spațiul de nume „std” în spațiul de nume global. folosind namespace std ; // Declaram un container asociativ cu chei sir si date ca vectori sir. map < șir , vector < șir > > elemente ; // Adăugați câteva persoane în acest container asociativ și dați-le câteva articole. articole [ „Anya” ]. push_back ( "esarfa" ); articole [ „Dmitry” ]. push_back ( "bilete" ); articole [ „Anya” ]. push_back ( "catel" ); // Buclă prin toate obiectele din container pentru ( const auto & person : items ) { // persoană este o pereche de două obiecte: person.first este numele său, // person.second este o listă a elementelor sale (vector de șiruri) cout << person . primul << " poartă " << persoană . al doilea . dimensiune () << "articole" << endl ; } }Acest exemplu importă toate numele din spațiul de nume standard pentru simplitate. Într-un program real, acest lucru nu este recomandat, deoarece puteți întâlni coliziuni de nume. Limbajul vă permite să importați obiecte individuale:
#include <vector> int main () { folosind std :: vector ; vector < int > vectorul_meu ; }În C++ (ca și în C), dacă execuția programului ajunge la sfârșitul funcției main(), atunci aceasta este echivalentă cu return 0;. Acest lucru nu este valabil pentru nicio altă funcție decât main().
Sunt cunoscute mai multe studii în care s-a încercat compararea mai mult sau mai puțin obiectivă a mai multor limbaje de programare, dintre care unul este C++. În special:
Limbajul Ada este aproape de C++ în ceea ce privește setul său de caracteristici și domenii de aplicare: este un limbaj structural compilat cu o adăugare orientată pe obiect asemănătoare Simula (același model „Algol cu clase” ca și în C++), tastare statică , instrumente de programare generice, concepute pentru dezvoltarea de sisteme software mari și complexe. În același timp, este fundamental diferită în ideologie: spre deosebire de C ++, Ada a fost construită pe baza unor condiții elaborate anterior cu atenție de la producători de software complex, cu cerințe sporite de fiabilitate, care au lăsat o amprentă asupra sintaxei și semanticii limba.
Există puține comparații directe ale eficienței codării Ada și C++. În articolul [22] menționat mai sus, rezolvarea problemei modelului în Ada a rezultat într-un cod cu aproximativ 30% mai mic ca dimensiune (în linii) decât în C++. Comparația proprietăților limbilor înseși este dată în multe surse, de exemplu, articolul lui Jim Rogers despre AdaHome [28] enumeră mai mult de 50 de puncte de diferențe între proprietățile acestor limbi, majoritatea fiind în favoarea lui Ada. (mai multe caracteristici, comportament mai flexibil, șanse mai mici de erori). Deși multe dintre declarațiile susținătorilor Ada sunt controversate, iar unele dintre ele sunt vădit depășite, în general se poate concluziona:
Într-un articol al lui Stephen Zeiger de la Rational Software Corporation [29] , se susține că dezvoltarea în Ada este în general cu 60% mai ieftină și are ca rezultat codul cu de 9 ori mai puține defecte decât în C. Deși aceste rezultate nu pot fi transferate direct în C++, ele sunt încă interesante, având în vedere că multe dintre deficiențele C++ sunt moștenite din C.
Java nu poate fi considerat un înlocuitor complet pentru C++, este conceput ca un limbaj sigur cu un prag de intrare scăzut pentru dezvoltarea aplicațiilor personalizate cu portabilitate ridicată [30] și este fundamental nepotrivit pentru unele tipuri de aplicații care sunt dezvoltate în C++. Cu toate acestea, în domeniul său de aplicare, Java este un concurent foarte real pentru C++. Beneficiile Java sunt frecvent citate ca:
În același timp, utilizarea colectorului de gunoi și a mașinii virtuale creează limitări greu de depășit. Programele Java tind să fie mai lente, necesită mult mai multă memorie, iar mașina virtuală izolează programul de sistemul de operare, făcând imposibilă programarea la nivel scăzut.
Un studiu empiric [24] nu a găsit nicio diferență semnificativă în viteza de dezvoltare în C++ și Java. Studiul [26] a mai arătat că ideea unei diferențe semnificative în viteza programelor în aceste limbi nu este întotdeauna corectă: în două din trei teste, viteza aplicațiilor în Java și C++ s-a dovedit a fi comparabil. În același timp, Java este mai concis - diferența în cantitatea de cod a fost de aproximativ 10-15%.
C-ul original continuă să evolueze, în el sunt dezvoltate multe proiecte la scară largă: este limbajul principal pentru dezvoltarea sistemelor de operare, motoarele de joc ale multor jocuri dinamice și un număr mare de aplicații sunt scrise în el. O serie de experți susțin că înlocuirea C cu C++ nu crește eficiența dezvoltării, ci duce la complicații inutile ale proiectului, la o fiabilitate redusă și la creșterea costurilor de întreținere. În special:
Nu există dovezi convingătoare că C++ este superior C, fie în ceea ce privește productivitatea programatorului, fie proprietățile programului. Deși există studii [32] care afirmă că programatorii C petrec aproximativ 30-40% din timpul total de dezvoltare (excluzând depanarea) pentru gestionarea memoriei, atunci când se compară productivitatea generală a dezvoltatorilor [22] , C și C++ sunt apropiate.
În programarea de nivel scăzut, multe dintre noile caracteristici ale C++ sunt inaplicabile din cauza supraîncărcării crescute: funcțiile virtuale necesită calcularea dinamică a adreselor reale (RVA), șabloanele duc la umflarea codului și capabilități slabe de optimizare, biblioteca de rulare (RTL) este foarte mare, iar respingerea acestuia privează majoritatea caracteristicilor C++ (fie doar din cauza indisponibilității new/ operațiunilor delete). Ca urmare, programatorul va trebui să se limiteze la funcționalitatea moștenită de la C, ceea ce face inutilă utilizarea C++:
… singura modalitate de a avea un C++ bun, eficient, de nivel scăzut și portabil este să te limitezi la toate lucrurile care sunt trivial disponibile în C. Și limitarea proiectului la C va însemna că oamenii nu îl vor arunca și că vor fi o mulțime de programatori disponibili care înțeleg bine caracteristicile de nivel scăzut și nu le abandonează din cauza „modelului obiectului” idiot. Prostii.
… când eficiența este primordială, „avantajele” C++ vor fi o mare greșeală.
Într-un experiment [22] , limbajele de scripting și funcționale, în special Haskell , au arătat un câștig de 2-3 ori în timpul de programare și dimensiunea codului în comparație cu programele C++. Pe de altă parte, programele C++ s-au dovedit a fi la fel de mult mai rapide. Autorii recunosc că datele lor nu constituie un eșantion reprezentativ și se abțin de la a face concluzii categorice.
Într-un alt experiment [34] , limbaje funcționale stricte ( Standard ML , OCaml ) au arătat o accelerare generală a dezvoltării cu un factor de 10 (în principal din cauza detectării timpurii a erorilor) cu indicatori de performanță aproximativ egali (mulți compilatori în mai multe moduri au fost folosit).
Într-un studiu realizat de Lutz Prehelt [24] , pe baza rezultatelor prelucrării a circa 80 de soluții scrise de voluntari, s-au obținut următoarele concluzii, în special:
Cel mai adesea, criticii nu opun C++ oricărui alt limbaj specific, dar susțin că respingerea utilizării unui singur limbaj care are numeroase defecte în favoarea descompunerii unui proiect în subsarcini care pot fi rezolvate în diferite limbi care sunt cele mai potrivite pentru ele fac dezvoltarea mult mai puțin consumatoare de timp, îmbunătățind în același timp indicatorii de calitate a programării [35] [36] . Din același motiv, menținerea compatibilității cu C este criticată: dacă o parte a sarcinii necesită caracteristici de nivel scăzut, este mai rezonabil să separați această parte într-un subsistem separat și să o scrieți în C.
La rândul lor, susținătorii C++ susțin că eliminarea problemelor tehnice și organizatorice ale interacțiunii interlingvistice prin utilizarea unei singure limbi universale în locul mai multor limbi specializate este mai importantă decât pierderile din imperfecțiunea acestui limbaj universal, adică foarte lărgimea setului de caracteristici C ++ este o scuză pentru deficiențele fiecărei caracteristici individuale; inclusiv dezavantajele moștenite de la C sunt justificate de avantajele compatibilității (vezi mai sus ).
Astfel, aceleași proprietăți ale C++ - volumul, complexitatea, eclectismul și lipsa unei nișe țintă specifice de aplicare - sunt considerate de susținători drept „ principalul avantaj ”, iar de critici – ca „ principalul dezavantaj ”.
Ideologia limbajului confundă „ controlul comportamentului ” cu „ controlul eficienței ”: principiul „ nu plătești pentru ceea ce nu folosești ” sugerează că oferirea programatorului control complet asupra tuturor aspectelor execuției programului la un nivel destul de scăzut este o condiție necesară și suficientă pentru a obține o eficiență ridicată a codului. De fapt, acest lucru nu este adevărat pentru niciun program mare: impunerea de optimizare la nivel scăzut asupra programatorului, pe care un compilator de limbaj specific domeniului de înaltă calitate este evident capabil să o execute mai eficient, duce doar la o creștere a cantității de cod, o creștere a intensității muncii de programare și o scădere a înțelegerii și testabilității codului. Astfel, principiul „nu plăti pentru ceea ce nu se folosește” nu oferă cu adevărat beneficiile dorite în eficiență, dar afectează negativ calitatea.
Programare orientată pe componente și pe obiectePotrivit lui Alan Kay , modelul obiect „ Algol cu clase” folosit în C++ este inferior modelului „totul este un obiect” [37] utilizat în Objective-C în ceea ce privește domeniul general, reutilizarea codului , înțelegerea, modificarea și testabilitatea. .
Modelul de moștenire C++ este complex, greu de implementat și provoacă în același timp crearea de ierarhii complexe cu relații nefirești între clase (de exemplu, moștenire în loc de imbricare). Rezultatul este crearea unor clase strâns cuplate , cu funcționalități vag separate. De exemplu, în [38] este dat un exemplu educațional și de recomandare de implementare a clasei „listă” ca subclasă a clasei „element listă”, care, la rândul său, conține funcții de acces pentru alte elemente de listă. Această relație de tip este matematic absurdă și ireproductibilă în limbaje mai riguroase. Ideologia unor biblioteci necesită introducerea manuală a tipurilor în sus și în jos în ierarhia claselor ( static_castși dynamic_cast), ceea ce încalcă siguranța tipului a limbajului. Vâscozitatea ridicată a soluțiilor C++ poate necesita redezvoltarea unor părți mari din proiect cu modificări minime mai târziu în procesul de dezvoltare. Un exemplu viu de astfel de probleme poate fi găsit în [35]
După cum subliniază Ian Joyner [39] , C++ echivalează în mod eronat încapsularea (adică introducerea datelor în interiorul obiectelor și separarea implementării de interfață) și ascunderea implementării. Acest lucru complică accesul la datele clasei și necesită ca interfața acesteia să fie implementată aproape exclusiv prin funcții accesorii (care, la rândul lor, mărește cantitatea de cod și o complică).
Potrivirea tipurilor în C++ este definită la nivel de identificatori, nu de semnături. Acest lucru face imposibilă înlocuirea componentelor pe baza potrivirii interfeței, motiv pentru care includerea de noi funcționalități implementate la nivel de bibliotecă în sistem necesită modificarea manuală a codului existent [40] . După cum subliniază Linus Torvalds [33] , în C++, „Codul pare abstract doar atâta timp cât nu trebuie schimbat”.
Critica C++ din punctul de vedere al OOP este dată în [39] .
MetaprogramareMetaprogramarea generativă a C++ este bazată pe șablon și preprocesor , necesită multă muncă și are un domeniu limitat. Sistemul de șabloane C++ este de fapt o variantă în timp de compilare a limbajului de programare funcțional primitiv. Acest limbaj nu are aproape nicio suprapunere cu C++ în sine, motiv pentru care potențialul de creștere a complexității abstracțiilor este limitat. Programele care folosesc șabloane C++ au o înțelegere și testabilitate extrem de slabe, iar dezasamblarea șablonului în sine generează cod ineficient, deoarece limbajul șablonului nu oferă niciun mijloc de optimizare (vezi și secțiunea #Eficiență computațională ). Limbajele încorporate specifice domeniului implementate în acest mod necesită încă cunoștințe despre C++ în sine, care nu oferă o diviziune completă a muncii. Astfel, capacitatea C++ de a extinde capabilitățile C++ în sine este destul de limitată [41] [42] .
MultiplatformăScrierea codului C++ portabil necesită o mare abilitate și experiență, iar codul C++ „neînsăcit” este foarte probabil să fie neportabil [43] . Potrivit lui Linus Torvalds , pentru a obține o portabilitate C++ similară cu C, programatorul trebuie să se limiteze la caracteristicile C++ moștenite din C [33] . Standardul conține multe elemente definite ca „definite de implementare” (de exemplu, dimensiunea pointerilor către metodele de clasă în diferite compilatoare variază de la 4 la 20 de octeți [44] ), ceea ce înrăutățește portabilitatea programelor care le folosesc.
Natura directivă a standardizării limbajului , compatibilitatea incompletă cu înapoi și inconsecvența cerințelor diferitelor versiuni ale standardului duc la probleme în portarea programelor între compilatoare diferite și chiar versiuni ale acelorași compilatoare.
Limbajul conține instrumente care permit programatorului să încalce disciplina de programare dată într-un anumit caz. De exemplu, un modificator constsetează proprietatea de imuabilitate a stării pentru un obiect, dar modificatorul mutableeste conceput special pentru a forța permisiunea de a schimba starea în interiorul unui obiect const, adică pentru a încălca constrângerea constness. Mai mult, este permisă eliminarea dinamică a unui atribut constdintr-un obiect constant, transformându-l într-o valoare L. Prezența unor astfel de caracteristici în limbaj face ca încercările de a verifica oficial codul să fie lipsite de sens, iar utilizarea restricțiilor pentru optimizare este imposibilă.
Înlocuire macro necontrolatăFacilitățile de substituție macro C ( #define) sunt pe cât de puternice, pe atât de periculoase. Ele sunt reținute în C++ în ciuda faptului că, pentru toate sarcinile pentru care au fost furnizate în C, C++ a oferit facilități mai stricte și specializate - șabloane, supraîncărcare de funcții, funcții inline, spații de nume, tastare mai avansată, extensie a aplicației modificatorul const. , etc. Există multe macrocomenzi potențial periculoase în bibliotecile standard moștenite de la C [45] . Metaprogramarea șablonului este, de asemenea, uneori combinată cu utilizarea substituției macro pentru a oferi așa-numitele. „ zahăr sintactic ”.
Probleme de supraîncărcarePrincipiile C++ ale supraîncărcării funcțiilor și operatorilor conduc la o duplicare semnificativă a codului. Intenționat inițial să introducă așa-numitul „ zahăr sintactic ”, supraîncărcarea operatorilor în C++ încurajează comportamentul necontrolat al operatorilor elementari pentru diferite tipuri. Acest lucru crește dramatic riscul de erori, mai ales că este imposibil să se introducă o nouă sintaxă și să se schimbe pe cea existentă (de exemplu, crearea de noi operatori sau modificarea priorităților sau asociativității), deși sintaxa operatorilor standard C++ este adecvată semantică de departe de toate tipurile care ar putea trebui introduse în program. Unele probleme sunt create de posibilitatea supraîncărcării ușoare a operatorilor / , care poate genera erori extrem de insidioase și greu de găsit. În același timp, unele operații așteptate intuitiv (curățarea obiectelor dinamice în cazul aruncării de excepții) nu sunt efectuate în C++, iar o parte semnificativă a funcțiilor și operatorilor supraîncărcați sunt chemați implicit (casting de tip, crearea de instanțe temporare de clase etc. .). Ca rezultat, instrumentele inițial destinate să clarifice programele și să îmbunătățească dezvoltarea și mentenabilitatea devin încă o sursă de cod inutil de complicat și nesigur. newdelete
Utilizarea șabloanelor C++ este un polimorfism parametric la nivel de cod sursă, dar atunci când este tradus, se transformă într -un polimorfism ad-hoc (adică supraîncărcare de funcții), ceea ce duce la o creștere semnificativă a cantității de cod mașină în comparație cu limbile care au un adevărat sistem de tip polimorf (descendenții lui ML ). Pentru a reduce dimensiunea codului de mașină, ei încearcă să proceseze automat codul sursă înainte de etapa de derulare a șabloanelor [46] [47] . O altă soluție ar putea fi posibilitatea de a exporta șabloane, care a fost standardizată încă din 1998, dar nu este disponibilă în toate compilatoarele, deoarece este dificil de implementat [48] [49] [opinii 4] și pentru importarea bibliotecilor de șabloane C++ în limbi cu o semantică C++ semnificativ diferită, ar fi încă inutil. Susținătorii C++ contestă gradul de umflare a codului ca fiind exagerat [50] , ignorând chiar faptul că în C polimorfismul parametric este tradus direct, adică fără a dubla corpuri de funcții deloc. În același timp, susținătorii C++ consideră că polimorfismul parametric în C este periculos - adică mai periculos decât trecerea de la C la C++ (oponenții lui C++ susțin contrariul - vezi mai sus).
Potenţial de optimizareDatorită sistemului de tip slab și abundenței efectelor secundare , devine extrem de dificilă convertirea echivalentă a programelor și, prin urmare, încorporarea multor algoritmi de optimizare în compilator, cum ar fi paralelizarea automată a programelor , eliminarea subexpresiilor comune , λ-lifting, apeluri la proceduri cu trecere în continuare , supercompilare , etc. Ca urmare, eficiența reală a programelor C++ este limitată de abilitățile programatorilor și de eforturile investite într-un anumit proiect, iar o implementare „neîncetată” poate fi semnificativ inferioară ca eficiență față de „neîncetată”. ” implementări în limbi de nivel superior, ceea ce este confirmat de teste comparative de limbi [34] . Aceasta este o barieră semnificativă împotriva utilizării C++ în industria data mining .
Gestionare eficientă a memorieiResponsabilitatea pentru gestionarea eficientă a memoriei cade pe umerii dezvoltatorului și depinde de abilitățile dezvoltatorului. Pentru gestionarea automată a memoriei în C++, așa-numita. „indicatoare inteligente”, gestionarea manuală a memoriei reduce eficiența programatorilor înșiși (a se vedea secțiunea Eficiență ) . Numeroase implementări de colectare a gunoiului , cum ar fi inferența statică a regiunilor , nu sunt aplicabile pentru programele C++ (mai precis, acest lucru necesită implementarea unui nou interpret de limbaj pe lângă limbajul C++, care este foarte diferit de C++ atât în majoritatea proprietăților obiective). și în general ideologie) datorită necesității de acces direct la AST .
Corelarea factorilor de performanță cu costurile de dezvoltare, precum și disciplina generală și cultura de programare cultivată în comunitatea de programare, sunt importante pentru clienții care aleg un limbaj (și, în consecință, preferă acest limbaj al dezvoltatorilor) pentru implementarea proiectelor lor, precum și pentru persoanele care încep să învețe programarea, mai ales cu intenția de a programa pentru propriile nevoi.
Calitatea și cultura programăriiPrincipiul C++ „ de a nu impune un „stil „bun” de programare ” este contrar abordării industriale a programării, în care rolul principal îl joacă calitatea software-ului și posibilitatea menținerii codului nu numai de către autor. și pentru care se preferă limbaje care minimizează influența factorului uman , adică doar „ impunerea unui stil „bun” de programare ”, deși astfel de limbaje pot avea un prag de intrare mai mare.
Există o părere că preferința pentru utilizarea C++ (cu posibilitatea de a alege limbaje alternative) caracterizează negativ calitățile profesionale ale unui programator. Mai exact, Linus Torvalds spune că folosește opiniile pozitive ale candidaților despre C++ ca criteriu de abandon [opinii 3] :
C++ este un limbaj teribil. Ceea ce îl face și mai îngrozitor este faptul că o mulțime de programatori nealfabetizați îl folosesc... Sincer, chiar dacă nu există niciun motiv pentru a alege C, în afară de a-i ține departe pe programatorii C++, doar acesta ar fi un motiv suficient de bun pentru a utiliza C.
…Am ajuns la concluzia că aș prefera să dau afară pe oricine ar prefera să dezvolte un proiect în C++ decât în C, astfel încât această persoană să nu strice proiectul în care sunt implicat.
Evoluția continuă a limbajului încurajează (și uneori forțează) programatorii să schimbe din nou și din nou codul deja depanat - acest lucru nu numai că crește costul dezvoltării, dar implică și riscul introducerii de noi erori în codul depanat. În special, deși compatibilitatea cu C++ a fost inițial unul dintre principiile de bază ale C++, din 1999 C a încetat să mai fie un subset al C++, astfel încât codul C depanat nu mai poate fi folosit într-un proiect C++ fără modificări.
Complexitatea de dragul eiC++ este definit de apologeții săi drept „cel mai puternic” tocmai pentru că este plin de caracteristici periculoase, reciproc contradictorii. Potrivit lui Eric Raymond , acest lucru face din limbajul în sine un teren pentru autoafirmarea personală a programatorilor, transformând procesul de dezvoltare într-un scop în sine:
Programatorii sunt adesea indivizi extravaganți care se mândresc cu... capacitatea lor de a gestiona complexitatea și de a gestiona abstracțiile cu dexteritate. Adesea ei concurează între ei, încercând să-și dea seama cine poate crea „cele mai complicate și frumoase complexități”. ... rivalii cred că trebuie să concureze cu „decorurile” altora adăugându-le pe ale lor. Destul de curând, „tumoarea masivă” devine standardul industriei și toată lumea rulează programe mari, cu probleme pe care nici măcar creatorii lor nu le pot satisface.
…
… această abordare poate avea probleme dacă programatorii fac lucruri simple în moduri complexe, pur și simplu pentru că știu acele moduri și știu cum să le folosească.
Au fost observate cazuri când programatorii neglijenți, folosind dependența puternică de context a C ++ și lipsa capacității de a urmări definițiile macro de către compilator, au încetinit dezvoltarea proiectului scriind unul sau două în plus, corecte din punctul de vedere al compilatorului. de vedere, linii de cod, dar introducerea unei erori greu de detectat manifestată spontan pe cheltuiala lor. De exemplu:
#define if(a) if(rand())În limbile cu corectitudine dovedită , chiar și cu facilități macro avansate, este imposibil să faci daune în acest fel.
Produs nesigurO abundență nerezonabilă de efecte secundare, combinată cu o lipsă de control din partea sistemului de rulare al limbajului și un sistem de tip slab, face ca programele C++ să fie predispuse la blocări fatale imprevizibile (cele binecunoscute blocări cu mesaje precum „Încălcarea accesului”, „Funcția virtuală pură apel” sau „Programul a efectuat o operațiune ilegală și va fi închis”), ceea ce exclude utilizarea C++ cu cerințe ridicate pentru toleranța la erori. În plus, crește durata procesului de dezvoltare în sine [34] .
Management de proiectFactorii enumerați mai sus fac din complexitatea managementului de proiect C++ una dintre cele mai înalte din industria dezvoltării software.
James Coggins, un cronicar de patru ani pentru The C++ Report , explică:
Problema este că programatorii OOP au experimentat cu aplicații incestuoase și au urmărit un nivel scăzut de abstractizare. De exemplu, au construit clase precum „listă legată” în loc de „interfață cu utilizatorul” sau „faz de radiație” sau „model cu elemente finite”. Din păcate, verificarea puternică a tipurilor, care îi ajută pe programatorii C++ să evite erorile, face și mai dificilă construirea de obiecte mari din cele mici.
Singurul descendent direct al C++ este limbajul D , menit să fie o reelaborare a C++ pentru a rezolva problemele sale cele mai evidente. Autorii au abandonat compatibilitatea cu C, păstrând sintaxa și multe dintre principiile de bază ale C++ și introducând în limbaj caracteristici care sunt caracteristice noilor limbi. D nu are preprocesor, nu are fișiere de antet, nu are moștenire multiplă, ci un sistem de module, interfețe, matrice asociative, suport pentru unicode în șiruri de caractere, colectare de gunoi (în timp ce se menține posibilitatea de gestionare manuală a memoriei), multithreading încorporat, inferență de tip , declararea explicită a funcțiilor pure și a valorilor imuabile. Utilizarea lui D este foarte limitată, nu poate fi considerat un concurent real al C++.
Cel mai vechi competitor al C++ în sarcinile de nivel scăzut este Objective-C , construit tot pe principiul combinării C cu un model obiect, doar modelul obiect fiind moștenit de la Smalltalk . Objective-C, ca și descendentul său Swift , este utilizat pe scară largă pentru dezvoltarea de software pentru macOS și iOS.
Una dintre primele alternative la C++ în programarea aplicațiilor a fost limbajul Java . Este adesea considerat eronat un descendent direct al C++; de fapt, semantica Java este moștenită din limbajul Modula-2 , iar semantica de bază a C++ nu poate fi urmărită în Java. Având în vedere acest lucru și genealogia limbilor (Modula-2 este un descendent al Simula , ca C++, dar nu este C), Java este mai corect numit „ vărul secund ” al C++, mai degrabă decât „ moștenitorul ”. Același lucru se poate spune despre limbajul C# , deși procentul de afinitate cu C++ este puțin mai mare decât cel al Java.
O încercare de a combina securitatea și viteza de dezvoltare a Java și C# cu capabilitățile C++ a fost dialectul C++ gestionat (mai târziu C++/CLI ). A fost dezvoltat de Microsoft în primul rând pentru a porta proiectele C++ existente pe platforma Microsoft .NET. Programele rulează sub CLR și pot folosi întreaga gamă de biblioteci .NET, dar există o serie de restricții privind utilizarea caracteristicilor C++, care reduc efectiv C++ la C#. Acest dialect nu a primit o recunoaștere largă și este folosit în principal pentru a lega biblioteci scrise în C++ pur cu aplicațiile C #.
O modalitate alternativă de dezvoltare a limbajului C este de a-l combina nu cu programarea orientată pe obiecte, ci cu programarea aplicativă , adică îmbunătățirea abstracției, rigoarea și modularitatea programelor de nivel scăzut, oferind un comportament previzibil și transparență referențială . Exemple de lucru în acest sens sunt limbile BitC , Cyclone și Limbo . Deși există și încercări de succes de a utiliza FP în probleme în timp real fără integrare cu instrumente C [52] [53] [54] , încă în momentul de față (2013) în dezvoltare la nivel scăzut, utilizarea instrumentelor C într-o oarecare măsură are un raport mai bun intensitatea muncii cu eficienta. Dezvoltatorii Python și Lua au depus mult efort în Python și Lua pentru a se asigura că aceste limbaje sunt folosite de programatorii C++, astfel încât dintre toate limbajele care sunt strâns legate de FP, acestea sunt cele mai des notat că este utilizat împreună cu C++ în același proiect. Cele mai semnificative puncte de contact dintre C++ și FP sunt legăturile bibliotecilor wxWidgets și Qt dezvoltate în C++ cu o ideologie specifică C++ la Lisp , Haskell și Python (în majoritatea cazurilor, legăturile la limbaje funcționale sunt făcute pentru bibliotecile scrise în C sau alte limbaje funcționale).
Un alt limbaj considerat un concurent pentru C++ este Nemerle , care este rezultatul unei încercări de a combina modelul de tastare Hindley-Milner și un subset macro al Common Lisp cu C# [55] . În aceeași ordine de idei este F# de la Microsoft , un dialect al ML adaptat pentru mediul .NET.
O încercare de a crea un înlocuitor industrial pentru C/C++ a fost limbajul de programare Go dezvoltat de Google în 2009 . Autorii limbajului subliniază în mod direct că motivul creării sale au fost deficiențele procesului de dezvoltare cauzate de particularitățile limbajelor C și C++ [56] . Go este un limbaj imperativ compact, necomplicat, cu sintaxă asemănătoare C, fără preprocesor, tastare statică, tastare puternică, sistem de ambalare, management automat al memoriei, unele caracteristici funcționale, subsistem OOP construit economic fără suport pentru moștenirea implementării, dar cu interfețe și tastare duck , multithreading încorporat bazat pe coroutine și țevi (a-la Occam ). Limbajul este poziționat ca o alternativă la C++, adică, în primul rând, un mijloc de dezvoltare în grup a sistemelor de calcul extrem de complexe, inclusiv distribuite, permițând, dacă este necesar, programarea la nivel scăzut.
În aceeași nișă ecologică cu C/C++ se află Rust, dezvoltat în 2010 și întreținut de Mozilla Corporation , axat pe gestionarea sigură a memoriei fără utilizarea unui colector de gunoi . În special, planurile de a înlocui parțial C/C++ cu Rust au fost anunțate în 2019 de Microsoft [57] .
Dicționare și enciclopedii | ||||
---|---|---|---|---|
|
Limbaje de programare | |
---|---|
|
ISO | Standardele|
---|---|
| |
de la 1 la 9999 |
|
10000 până la 19999 |
|
20000+ | |
Vezi și: Lista articolelor ale căror titluri încep cu „ISO” |
C++ | |
---|---|
Particularități | |
Unele biblioteci | |
Compilatoare | |
influențat | |
|