C++ | |
---|---|
Semantiikka | moniparadigma : olio- , yleinen , proseduuri- , metaohjelmointi |
Kieliluokka | olioohjelmointikieli , moniparadigmaohjelmointikieli , prosessiohjelmointikieli , toiminnallinen ohjelmointikieli , yleinen ohjelmointikieli , ohjelmointikieli , vapaamuotoinen kieli [d] ja käännetty ohjelmointikieli |
Toteutustyyppi | koottu |
Esiintyi | 1983 |
Tekijä | Stroustrup, Björn |
Tiedostotunniste _ | .cc, .cpp, .cxx, .c, .c++, .h, .hpp, .hh, .hxxtai.h++ |
Vapauta | |
Tyyppijärjestelmä | staattinen |
Tärkeimmät toteutukset | GNU C++ , Microsoft Visual C++ , Intel C++ -kääntäjä , Open64 C++ -kääntäjä , Clang , Comeau C/C++ , Embarcadero C++ Builder , Watcom C++ -kääntäjä , Digital Mars C++, Oracle Solaris Studio C++ C++ compiler |
Murteet | ISO/IEC 14882 C++ |
Vaikutettu | C , Simula , Algol 68 , Clu , ML ja Ada |
Verkkosivusto | isocpp.org _ |
Mediatiedostot Wikimedia Commonsissa |
C ++ (lausutaan c-plus-plus [2] [3] ) on käännetty , staattisesti kirjoitettu , yleiskäyttöinen ohjelmointikieli .
Tukee sellaisia ohjelmointiparadigmoja kuin prosessiohjelmointi , olioohjelmointi , yleinen ohjelmointi . Kielessä on rikas standardikirjasto, joka sisältää yleisiä säilöjä ja algoritmeja , I/O:ta, säännöllisiä lausekkeita, monisäikeisen tuen ja paljon muuta. C++ yhdistää sekä korkean tason että matalan tason kielten ominaisuuksia [4] [5] . Edeltäjäänsä - C -kieleen - verrattuna eniten huomiota kiinnitetään olio- ja geneerisen ohjelmoinnin tukemiseen [5] .
C++ :aa käytetään laajalti ohjelmistokehitykseen, koska se on yksi suosituimmista ohjelmointikielistä [mielipiteitä 1] [mielipiteitä 2] . Sen soveltamisalaan kuuluu käyttöjärjestelmien , erilaisten sovellusohjelmien, laiteajureiden , sulautettujen järjestelmien sovellusten, tehokkaiden palvelimien ja tietokonepelien luominen. C++-kielellä on monia toteutuksia, sekä ilmaisia että kaupallisia, ja eri alustoille. Esimerkiksi x86 -alustalla näitä ovat GCC , Visual C++ , Intel C++ Compiler , Embarcadero (Borland) C++ Builder ja muut. C++:lla on ollut valtava vaikutus muihin ohjelmointikieliin, erityisesti Javaan ja C# :ään .
C++-syntaksi on peritty C -kielestä . Yksi alkuperäisistä suunnitteluperiaatteista oli säilyttää yhteensopivuus C:n kanssa. C++ ei kuitenkaan ole tiukasti C:n superjoukko; Sekä C- että C++-kääntäjät pystyvät kääntämään yhtä hyvin ohjelmia, jotka ovat melko suuria, mutta ne eivät sisällä kaikkia mahdollisia C-ohjelmia .
Historiallinen kehitysvaihe [6] | vuosi |
---|---|
BCPL kieli | 1966 |
B- kieli ( alkuperäinen Thompsonin kehittämä UNIX -käyttöjärjestelmä ) | 1969 |
C -kieli | 1972 |
C luokkien kanssa | 1980 |
C84 | 1984 |
Cfront (E-painos) | 1984 |
cfront (julkaisu 1.0) | 1985 |
Moninkertainen/virtuaalinen perintö | 1988 |
Yleinen ohjelmointi ( mallit ) | 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 |
Kieli syntyi 1980-luvun alussa , kun Bell Labsin työntekijä Björn Stroustrup keksi useita parannuksia C -kieleen omiin tarpeisiinsa [7] . Kun Stroustrup aloitti työskentelyn Bell Labsissa 1970-luvun lopulla jonoteorian ongelmien parissa (jota sovellettiin puheluiden mallintamiseen), hän havaitsi, että yritykset käyttää tuolloin olemassa olevia mallintamiskieliä olivat tehottomia ja erittäin tehokkaiden konekielien käyttö. oli liian vaikeaa niiden rajallisen ilmaisukyvyn vuoksi. Esimerkiksi Simula -kielessä on ominaisuuksia, jotka olisivat erittäin hyödyllisiä suurten ohjelmistojen kehittämiseen, mutta se on liian hidas, ja BCPL -kieli on riittävän nopea, mutta liian lähellä matalan tason kieliä, eikä se sovellu suurten ohjelmistojen kehittämiseen.
Väitöskirjasta saatuja kokemuksia muisteleva Stroustrup päätti täydentää C-kieltä (BCPL:n seuraaja) Simula-kielellä saatavilla olevilla ominaisuuksilla. C-kieli, joka on UNIX -järjestelmän peruskieli , jolla Bell-tietokoneet toimivat, on nopea, monipuolinen ja kannettava. Stroustrup lisäsi siihen kyvyn työskennellä luokkien ja objektien kanssa. Tämän seurauksena käytännön mallinnusongelmat osoittautuivat saavutettavissa oleviksi sekä kehitysajassa (johtuen Simula-tyyppisten luokkien käytöstä) että laskentaajassa (johtuen C:n nopeudesta). Ensimmäiset C:n lisäykset olivat luokat ( kapseloimalla ), luokan periytyminen, tiukka tyyppitarkistus, rivifunktiot ja oletusargumentit . Kielen varhaiset versiot, alun perin nimeltään "C with classes", ovat olleet saatavilla 1980- luvulta lähtien .
Kun kehitti C:tä luokkien kanssa , Stroustrup kirjoitti ohjelman cfront , kääntäjän , joka muokkaa C-lähdekoodin luokkien kanssa tavalliseksi C-lähdekoodiksi. Tämä antoi meille mahdollisuuden työstää uutta kieltä ja käyttää sitä käytännössä UNIXissa jo saatavilla olevan infrastruktuurin avulla. Kehitys kielessä C. Uusi kieli, kirjoittajalle odottamatta, hän saavutti suuren suosion kollegoiden keskuudessa ja pian Stroustrup ei enää voinut tukea häntä henkilökohtaisesti ja vastasi tuhansiin kysymyksiin.
Vuoteen 1983 mennessä kieleen lisättiin uusia ominaisuuksia, kuten virtuaalifunktiot, toimintojen ja operaattorien ylikuormitus, viittaukset, vakiot, vapaan muistin hallinta, parannettu tyyppitarkistus ja uusi kommenttityyli ( //). Tuloksena oleva kieli ei ole enää vain klassisen C:n lisätty versio, ja se on nimetty uudelleen C:stä luokkien kanssa "C++". Sen ensimmäinen kaupallinen julkaisu tapahtui lokakuussa 1985 .
Ennen virallisen standardoinnin alkamista kielen kehitti pääasiassa Stroustrup vastauksena ohjelmointiyhteisön pyyntöihin. Standardikielisten kuvausten toiminnon suorittivat Stroustrupin C ++:lla painetut teokset (kielen kuvaus, viiteopas ja niin edelleen). Vasta vuonna 1998 ratifioitiin C++-kielen kansainvälinen standardi: ISO/IEC 14882:1998 "Standard for the C++ Programming Language"; Standardiin vuonna 2003 tehtyjen teknisten korjausten hyväksymisen jälkeen tämän standardin seuraava versio on ISO/IEC 14882:2003 [8] .
Vuonna 1985 julkaistiin C++-ohjelmointikielen ensimmäinen painos , joka sisälsi ensimmäisen kuvauksen kielestä, mikä oli erittäin tärkeää virallisen standardin puutteen vuoksi. Vuonna 1989 julkaistiin C++-versio 2.0. Sen uusiin ominaisuuksiin kuuluivat useat periytymiset, abstraktit luokat, staattiset jäsenfunktiot, vakiofunktiot ja suojatut jäsenet. Vuonna 1990 julkaistiin "Commented Reference Guide to C++", josta tuli myöhemmin standardin perusta. Viimeaikaiset päivitykset ovat sisältäneet malleja, poikkeuksia, nimiavaruuksia, uusia casteja ja boolean-tyyppiä. Alexander Stepanovin ja Meng Li kehittämä Standard Template Library (STL) valittiin perustaksi yleisten algoritmien tallentamiselle ja käyttämiselle .
C++ Standard Library on myös kehittynyt sen mukana. Ensimmäinen lisäys C++-standardikirjastoon olivat I/O-virrat, jotka tarjosivat keinon korvata perinteiset C- printfja scanf. Myöhemmin standardikirjaston merkittävin kehitystyö oli Standard Template Libraryn sisällyttäminen .
C++ kehittyy jatkuvasti vastaamaan nykyajan vaatimuksia. Yksi C ++ -kieltä kehittävistä ja sen parannusehdotuksia C ++ -standardointikomitealle lähettävistä ryhmistä on Boost , joka muun muassa kehittää kielen ominaisuuksia lisäämällä siihen metaohjelmointiominaisuuksia .
Kukaan ei omista oikeuksia C++-kieleen, se on ilmainen. Itse kielistandardiasiakirja (luonnoksia lukuun ottamatta) ei kuitenkaan ole vapaasti saatavilla [10] . Osana standardointiprosessia ISO tuottaa monenlaisia julkaisuja. Erityisesti tekniset raportit ja tekniset spesifikaatiot julkaistaan, kun "tulevaisuus on näköpiirissä, mutta ei ole välitöntä mahdollisuutta päästä sopimukseen kansainvälisen standardin julkaisemisesta". Vuoteen 2011 asti julkaistiin kolme C++:n teknistä raporttia: TR 19768: 2007 (tunnetaan myös nimellä C++ Technical Report 1) pääasiassa C++11:een integroiduille kirjastolaajennuksille, TR 29124: 2010 matemaattisille erityisfunktioille ja TR 24733: 2011. desimaaliliukulukuaritmetiikka. Tekniset tiedot DTS 18822:. 2014 (tiedostojärjestelmällä) hyväksyttiin vuoden 2015 alussa, ja loput spesifikaatiot ovat kehitteillä ja odottavat hyväksyntää [11] .
Maaliskuussa 2016 Venäjälle perustettiin työryhmä WG21 C++ . Ryhmä perustettiin keräämään C++-standardia koskevia ehdotuksia, toimittamaan ne komitealle ja puolustamaan niitä Kansainvälisen standardointijärjestön (ISO) yleiskokouksissa [12] .
Tuloksena oleva kielen nimi tulee C unary++ postfix -operaattorista (muuttujan arvo kasvaa yhdellä). Nimeä C+ ei käytetty, koska se on C :n syntaksivirhe ja lisäksi nimi on otettu toisella kielellä. Kieltä ei myöskään nimetty D:ksi, koska "se on C:n laajennus eikä yritä korjata ongelmia poistamalla C-elementtejä " [7] .
Teoksessa The Design and Evolution of C++ [13] Bjorn Stroustrup kuvaa periaatteita, joita hän noudatti C++:n suunnittelussa. Nämä periaatteet selittävät, miksi C++ on sellainen kuin se on. Jotkut heistä:
C++-standardi koostuu kahdesta pääosasta: ydinkielen kuvauksesta ja standardikirjaston kuvauksesta.
Aluksi kieli kehittyi muodollisen viitekehyksen ulkopuolella, spontaanisti sitä kohtaavien tehtävien mukaisesti. Kielen kehitystä seurasi cfront - ristikääntäjän kehittäminen . Kielen innovaatiot näkyivät ristikääntäjän versionumeron muutoksena. Nämä ristiinkääntäjän versionumerot ulottuivat itse kieleen, mutta C++-versioista ei tällä hetkellä keskustella. Vasta vuonna 1998 kieli standardisoitiin.
Nimetön nimiavaruus on erikoistapaus. Kaikki siinä kuvatut nimet ovat saatavilla vain nykyisessä käännösyksikössä ja niillä on paikallinen sidonta. Nimiavaruus stdsisältää tavalliset C++-kirjastot.
Seuraavat sisäänrakennetut tyypit ovat saatavilla C++:ssa. C++-tyypit ovat lähes identtisiä C-tietotyyppien kanssa :
Vertailuoperaattorien palautustyyppi bool. Suluissa , jälkeen olevat lausekkeet ifmuunnetaan while tyypiksi bool[14] .
Kielessä otettiin käyttöön viitteiden käsite ja C++11- standardista rvalues - viittaukset ja edelleenlähetysviitteet . (katso linkki (C++) )
C++ lisää oliopohjaisia ominaisuuksia C:hen. Se esittelee luokat, jotka tarjoavat OOP : n kolme tärkeintä ominaisuutta : kapseloinnin , periytymisen ja polymorfismin .
C++-standardissa luokka on käyttäjän määrittämä tyyppi, joka on ilmoitettu käyttämällä jotakin avainsanoista class, rakenne on luokka, structjonka unionmäärittelee struct, ja liitto on luokka, jonka määrittelee union. Käytetystä avainsanasta riippuen myös jotkin itse luokan ominaisuudet muuttuvat. Esimerkiksi luokassa, joka on ilmoitettu tunnuksella struct, jäsenet, joilla ei ole manuaalisesti määritettyä käyttöoikeusmuuttujaa, ovat oletuksena julkisia yksityisen sijaan.
Luokkamäärittelyn rungossa voit määrittää sekä funktion ilmoitukset että niiden määritelmät. Jälkimmäisessä tapauksessa funktio on rivissä ( inline). Ei-staattisilla jäsenfunktioilla voi olla tarkenteita constja volatilesekä viitetunniste ( &tai &&).
C++ tukee moniperintöä . Perusluokat (esivanhemmat luokat) on määritelty luokkamäärittelyn otsikossa, mahdollisesti käyttöoikeusmääritteineen. Jokaisen luokan perintö voi olla julkista, suojattua tai yksityistä:
Perusluokan jäsenten pääsy-/perintötila | yksityinen jäsen | suojattu jäsen | julkinen jäsen |
---|---|---|---|
yksityinen perintö | ei saatavilla | yksityinen | yksityinen |
suojattu perintö | ei saatavilla | suojattu | suojattu |
julkinen perintö | ei saatavilla | suojattu | julkinen |
Oletuksena perusluokka peritään yksityisenä.
Perinnön seurauksena lapsiluokka saa kaikki esivanhempien luokkien kentät ja kaikki niiden menetelmät; voimme sanoa, että jokainen jälkeläisluokan ilmentymä sisältää kunkin esivanhemman luokan ali-ilmentymän. Jos yksi esi-isäluokka periytyy useita kertoja (tämä on mahdollista, jos se on luotavan luokan useiden perusluokkien esi-isä), jälkeläisluokan esiintymät sisältävät niin monta ali-instanssia tästä esi-isä-luokasta. Tämän vaikutuksen välttämiseksi, jos sitä ei haluta, C++ tukee virtuaaliperinnön käsitettä . Periessään perusluokka voidaan julistaa virtuaaliseksi; kaikille esivanhempien luokan virtuaalisille esiintymille jälkeläisen luokan perintöpuussa luodaan vain yksi ali-ilmentymä jälkeläiseen.
C++ tukee dynaamista polymorfismia ja parametrista polymorfismia .
Parametrista polymorfismia edustaa:
Dynaaminen polymorfismi toteutetaan käyttämällä virtuaalisia menetelmiä ja periytymishierarkiaa. C++:ssa tyyppi on polymorfinen, jos sillä on vähintään yksi virtuaalinen menetelmä. Esimerkki hierarkiasta:
luokka Kuva { julkinen : virtuaalinen tyhjyys Draw () = 0 ; // puhdas virtuaalinen menetelmä virtuaalinen ~ Kuva (); // jos on olemassa ainakin yksi virtuaalinen menetelmä, destruktorista tulee tehdä virtuaalinen }; luokka Neliö : julkinen hahmo { julkinen : void Draw () ohitus ; }; luokka Ympyrä : julkinen henkilö { julkinen : void Draw () ohitus ; };Tässä Figure-luokka on abstrakti (ja jopa rajapintaluokka ), koska Draw-menetelmää ei ole määritelty. Tämän luokan objekteja ei voida luoda, mutta viittauksia tai osoittimia, joiden tyyppi on Figure, voidaan käyttää. Draw-menetelmän toteutuksen valinta tehdään ajon aikana objektin todellisen tyypin perusteella.
C++:n kapselointi toteutetaan määrittämällä luokan jäsenten käyttöoikeustaso: ne ovat julkisia (julkinen, public), suojattuja ( protected) ja yksityisiä (yksityinen, private). C++:ssa rakenteet eroavat muodollisesti luokista vain siinä, että oletuksena luokan jäsenten käyttöoikeustaso ja rakenteen perinnön tyyppi ovat julkisia, kun taas luokilla ne ovat yksityisiä.
Pääsy | yksityinen | suojattu | julkinen |
---|---|---|---|
Itse luokka | Joo | Joo | Joo |
Ystävät | Joo | Joo | Joo |
perilliset | Ei | Joo | Joo |
Ulkopuolelta | Ei | Ei | Joo |
Pääsytarkistus tapahtuu käännösaikana, ja yrittäminen päästä käsiksi saavuttamattomiin luokan jäseniin aiheuttaa käännösvirheen.
YstävätYstävätoiminnot ovat toimintoja, jotka eivät ole jäsentoimintoja, mutta joilla on kuitenkin pääsy luokan suojattuihin ja yksityisiin jäseniin. Ne on ilmoitettava luokan rungossa muodossa friend. Esimerkiksi:
class Matrix { ystävä Matrix Multiply ( Matrix m1 , Matrix m2 ); };Tässä funktiolla Multiplyon pääsy kaikkiin :n kenttiin ja jäsentoimintoihin Matrix.
Sekä koko luokka että luokan jäsenfunktio voidaan julistaa ystäväksi. Neljä tärkeää rajoitusta ystäväsuhteille C++:ssa ovat:
Yleisesti ottaen tämä sääntö voidaan muotoilla seuraavasti: "Ystävällisyyssuhde on olemassa vain niiden luokkien (luokka ja toiminto) välillä, joille se on nimenomaisesti ilmoitettu koodissa, ja se toimii vain siihen suuntaan, johon se on ilmoitettu."
Oletusluokalla voi olla kuusi erikoistoimintoa: oletuskonstruktori, kopiointikonstruktori, siirtokonstruktori, tuhoaja, kopiointitehtäväoperaattori, siirtotehtäväoperaattori. Ne kaikki on myös mahdollista määritellä eksplisiittisesti (katso Kolmen sääntö ).
class Array { julkinen : Taulukko ( ) = oletusarvo // kääntäjä luo itse Arraylle oletusmuodostajan ( size_t _len ) : len ( _len ) { val = uusi tupla [ _len ]; } Array ( const Array & a ) = poista ; // kopiointikonstruktori eksplisiittisesti poistettu Array ( Array && a ); // siirrä konstruktoria ~ Array () { poista [] val ; } Array & operaattori = ( const Array & rhs ); // kopioi määritysoperaattori Array & operator = ( Array && rhs ); // siirrä tehtävän operaattori double & operator []( size_t i ) { paluuarvo [ i ] ; } const double & operaattori []( koko_t i ) const { paluuarvo [ i ] ; } suojattu : std :: koko_t len = 0 ; // kentän alustus double * val { nullptr }; };Konstruktoria kutsutaan alustamaan objekti (sopivan tyyppinen), kun se luodaan, ja tuhoajaa kutsutaan tuhoamaan objekti. Luokassa voi olla useita rakentajia, mutta destruktorilla voi olla vain yksi. C++:n konstruktoreita ei voida julistaa virtuaalisiksi, mutta destruktorit voidaan ja yleensä ilmoitetaan kaikille polymorfisille tyypeille, jotta varmistetaan, että viitattu tai osoittimen käytettävissä oleva objekti tuhotaan oikein riippumatta siitä, minkä tyyppinen viittaus tai osoitin on. Jos ainakin yhdellä perusluokista on virtuaalinen tuhoaja, aliluokan tuhoaja muuttuu automaattisesti virtuaaliseksi.
Mallien avulla voit luoda toimintoja ja luokkia, jotka on parametroitu tietyllä tyypillä tai arvolla. Esimerkiksi edellinen luokka voisi toteuttaa taulukon mille tahansa tietotyypille:
malli < typenameT > _ class Array { ... T & operaattori []( koko_t i ) { paluuarvo [ i ] ; } suojattu : std :: koko_t len { 0 }; // kentän alustus T * val { nullptr }; };C++ Standard Library sisältää joukon työkaluja, joiden pitäisi olla kaikkien kielen toteutusten käytettävissä, jotta ohjelmoijat voivat käyttää kieliominaisuuksia mukavasti ja luoda perusta sekä laajan valikoiman sovellussovelluksia että erikoiskirjastoja. C++-standardikirjasto sisältää osan C-standardikirjastosta. C++-standardi sisältää normatiivisen viittauksen vuoden 1990 C-standardiin , eikä se määrittele itsenäisesti niitä vakiokirjastotoimintoja, jotka on lainattu C-standardikirjastosta.
#includePääsy C++-standardikirjaston ominaisuuksiin saadaan sisällyttämällä ohjelmaan asianmukaiset vakiootsikkotiedostot (direktiivin kautta ). Yhteensä 79 tällaista tiedostoa on määritelty C++11-standardissa. Tavalliset kirjastopalvelut on ilmoitettu osana std-nimiavaruutta. Otsikkotiedostot, joiden nimet vastaavat mallia "cX", jossa X on C-standardikirjaston otsikkotiedoston nimi ilman tunnistetta (cstdlib, cstring, cstdio jne.), sisältävät ilmoitukset, jotka vastaavat sitä C-standardikirjaston osaa. vakiokirjastofunktiot löytyvät myös nimiavaruudesta std.
Vakiokirjasto sisältää seuraavat osat:
Säilöjä, merkkijonoja, algoritmeja, iteraattoreita ja perusapuohjelmia, lukuun ottamatta lainauksia C-kirjastosta, kutsutaan yhteisesti STL:ksi (Standard Template Library - vakiomallikirjasto). Aluksi tämä kirjasto oli erillinen tuote ja sen lyhenne tulkittiin eri tavalla, mutta sitten se tuli C ++ -standardikirjastoon kiinteänä elementtinä. Nimi kuvastaa sitä tosiasiaa, että yleistettyjä ohjelmointimekanismeja (C++ templates - template) käytetään yleiskäyttöisten työkalujen (säilöt, merkkijonot, algoritmit) toteuttamiseen. Stroustrupin kirjoituksissa kerrotaan yksityiskohtaisesti syyt, miksi tämä valinta tehtiin. Tärkeimmät niistä ovat valitun ratkaisun suurempi universaalisuus (mallisäiliöitä, toisin kuin objektisäiliöitä, voidaan helposti käyttää ei-objektityypeille, eivätkä ne vaadi elementtityypeille yhteistä esi-isä) ja sen tekninen tehokkuus (pääsääntöisesti mallisäiliö toiminnot eivät vaadi virtuaalisia funktiokutsuja ja ne voidaan helposti upottaa (inline), mikä lopulta parantaa suorituskykyä).
C++11-standardista alkaen seuraavat ominaisuudet on lisätty:
Ennen kuin STL sisällytettiin C++-standardiin, se oli kolmannen osapuolen kehittämä, ensin HP :n ja sitten SGI :n kehittämä . Kielistandardi ei kutsu sitä nimellä "STL", koska tästä kirjastosta on tullut kiinteä osa kieltä, mutta monet ihmiset käyttävät silti tätä nimeä erottaakseen sen muusta vakiokirjastosta (I/O-virrat ( iostream ), alaosa C ja muut).
Projekti nimeltä STLport [15] , joka perustuu SGI STL:ään, pitää STL-, IOstream- ja merkkijonoluokat ajan tasalla. Myös useat muut hankkeet kehittävät standardikirjaston yksityiskäyttöä.
C:n valinta uuden ohjelmointikielen luomisen perustaksi selittyy sillä, että C-kieli:
Huolimatta useista tunnetuista C-kielen puutteista, Stroustrup päätti käyttää sitä pohjana, koska "C:llä on ongelmansa, mutta tyhjästä suunnitellussa kielessä niitä olisi, ja me tiedämme C:n ongelmat." Lisäksi tämän ansiosta saimme nopeasti kääntäjän prototyypin ( cfront ), joka käänsi vain lisätyt syntaksielementit alkuperäiselle C-kielelle.
C++:n kehittyessä otettiin mukaan muita ominaisuuksia, jotka ohittavat C-konstruktien ominaisuudet, ja kysymys kielen yhteensopivuuden hylkäämisestä poistamalla vanhentuneet rakenteet nostettiin toistuvasti esille. Yhteensopivuus on kuitenkin säilytetty seuraavista syistä:
Uusia C++-ominaisuuksia ovat lausekemääritykset, funktiotyyppien muunnokset, operaattorit newja delete, tyyppi bool, viittaukset, laajennettu pysyvyys, rivifunktiot, oletusargumentit, ohitukset, nimiavaruudet, luokat (mukaan lukien kaikki luokkaan liittyvät ominaisuudet, kuten periytyminen, jäsenfunktiot, virtuaalifunktiot, abstrakti luokat ja rakentajat ), operaattorin ohitukset, mallit, operaattori ::, poikkeusten käsittely, dynaaminen tunnistus ja paljon muuta. C++-kieli on myös monissa tapauksissa tiukempi tyyppitarkistuksen suhteen kuin C.
C++ esitteli kaksoisviivakommentit ( //), jotka olivat C:n edeltäjässä BCPL .
constJotkut C++:n ominaisuudet siirrettiin myöhemmin C:hen, kuten ja avainsanat, silmukkailmoitukset inlineja forC++-tyyliset kommentit ( //). Myöhemmät C:n toteutukset toivat myös ominaisuuksia, joita ei löydy C++:sta, kuten makrot va_argja parannettu taulukkoparametrien käsittely.
Vaikka useimmat C-koodit kelpaavat myös C++:lle, C++ ei ole C:n superjoukko eikä sisällä sitä. On myös koodia, joka on totta C:lle, mutta ei totta C++:lle. Tämä erottaa sen Objective C :stä , toisesta C-parannuksesta OOP :lle , joka on vain C:n superjoukko.
Muitakin eroja on. Esimerkiksi C++ ei salli funktion kutsumista main()ohjelman sisällä, kun taas C:ssä se on laillista. Myös C++ on joissain suhteissa tiukempi; Se ei esimerkiksi salli implisiittistä heittämistä toisiinsa liittyvien osoitintyyppien välillä eikä salli toimintoja, joita ei ole vielä ilmoitettu.
Lisäksi molemmilla kielillä voimassa oleva koodi voi tuottaa erilaisia tuloksia riippuen siitä, minkä kielen kääntäjälle se on käännetty. Esimerkiksi useimmilla alustoilla seuraava ohjelma tulostaa "C", jos se on käännetty C-kääntäjällä, ja "C++", jos se on käännetty C++-kääntäjällä. Tämä johtuu siitä, että C:n merkkivakiot (esimerkiksi 'a') ovat tyyppiä int, mutta C++:ssa ne ovat tyyppiä charja näiden tyyppien koot yleensä vaihtelevat.
#include <stdio.h> int main () { printf ( "%s \n " , ( koko ( 'a' ) == koko ( char )) ? "C++" : "C" ); paluu 0 ; }Kuten Stroustrup huomauttaa, "Mitä paremmin tunnet C:n, sitä vaikeampaa sinun on välttää C++-ohjelmointia C-tyylillä samalla, kun menetät C++:n mahdolliset edut." Tätä varten hän antaa seuraavat suositukset C-ohjelmoijille, jotta he voivat hyödyntää C++:aa täysimääräisesti:
Nykyinen ISO/IEC 14882:2017 -kielistandardi julkaistiin joulukuussa 2017 . Sitä kutsutaan epävirallisesti C++17 :ksi . Standardin seuraava, vuodelle 2020 suunniteltu versio on saanut epävirallisen nimityksen C++20 .
Kielen kirjoittajan Björn Stroustrupin [19] [20] [21] mukaan kielen jatkokehityksestä ja tulevaisuudennäkymistä puhuttaessa voidaan erottaa seuraavaa:
Tämä on esimerkkiohjelma Hello, world! , joka tulostaa viestin konsoliin käyttämällä vakiokirjastoa ja poistuu.
#include <iostream> käyttäen nimiavaruutta std ; int main () { cout << "Hei, maailma!" << endl ; paluu 0 ; }Nykyaikainen C++ mahdollistaa monimutkaisempien ongelmien ratkaisemisen yksinkertaisella tavalla. Tämä esimerkki havainnollistaa muun muassa STL (Standard Template Library ) -säiliöiden käyttöä.
#include <iostream> // käyttääksesi std::cout #include <vektori> // sisältää dynaamisen taulukon #include <kartta> // sisältää sanakirjan tietotyypin #sisällytä <merkkijono> int main () { // Tuo kaikki "std"-nimiavaruuden ilmoitukset globaaliin nimiavaruuteen. käyttäen nimiavaruutta std ; // Ilmoitamme merkkijonovektoreiksi assosiatiivisen säiliön, jossa on merkkijonoavaimet ja tiedot. kartta < merkkijono , vektori < merkkijono > > kohteet ; // Lisää pari henkilöä tähän assosiatiiviseen säilöön ja anna heille joitain kohteita. kohteita [ "Anya" ]. push_back ( "huivi" ); kohteita [ "Dmitry" ]. push_back ( "liput" ); kohteita [ "Anya" ]. push_back ( "pentu" ); // Kierrä kaikki säilön objektit kohteelle ( const auto & person : items ) { // henkilö on kahden objektin pari: henkilö.first on sen nimi, // henkilö.toinen on luettelo sen kohteista (merkkijonovektori) cout << henkilö . ensimmäinen << " kantaa " << henkilöä . toinen . koko () << "tuotteet" << endl ; } }Tämä esimerkki tuo kaikki nimet std-nimiavaruudesta yksinkertaisuuden vuoksi. Oikeassa ohjelmassa tätä ei suositella, koska saatat kohdata nimien törmäyksiä. Kielen avulla voit tuoda yksittäisiä objekteja:
#sisällytä <vektori> int main () { käyttäen std :: vector ; vektori < int > oma_vektori ; }C++:ssa (kuten C:ssä), jos ohjelman suoritus saavuttaa funktion loppuun main(), tämä vastaa funktiota return 0;. Tämä ei päde millekään muulle toiminnolle kuin main().
Tunnetaan useita tutkimuksia, joissa on yritetty verrata enemmän tai vähemmän objektiivisesti useita ohjelmointikieliä, joista yksi on C ++. Erityisesti:
Ada-kieli on ominaisuuksiltaan ja sovellusalueiltaan lähellä C++:aa: se on käännetty rakennekieli, jossa on Simula-tyyppinen oliopohjainen lisäys (sama "Algol with classes" -malli kuin C++:ssa), staattinen kirjoitus. , yleiset ohjelmointityökalut, jotka on suunniteltu suurten ja monimutkaisten ohjelmistojärjestelmien kehittämiseen. Samalla se on ideologialtaan pohjimmiltaan erilainen: toisin kuin C ++, Ada rakennettiin monimutkaisten ohjelmistovalmistajien aiemmin huolellisesti laadittujen ehtojen pohjalta, joilla on lisääntyneet luotettavuusvaatimukset, mikä jätti jäljen ohjelmiston syntaksiin ja semantiikkaan. Kieli.
Ada- ja C++-koodauksen tehokkuudesta on vähän suoria vertailuja. Edellä mainitussa artikkelissa [22] malliongelman ratkaisu Adassa johti noin 30 % pienempään koodiin kooltaan (riveinä) kuin C++:ssa. Itse kielten ominaisuuksien vertailua on annettu monissa lähteissä, esimerkiksi Jim Rogersin artikkelissa AdaHomesta [28] luetellaan yli 50 kohtaa eroavaisuuksista näiden kielten ominaisuuksissa, joista suurin osa on Adan kannalla. (enemmän ominaisuuksia, joustavampi toiminta, pienempi virheiden mahdollisuus). Vaikka monet Adan kannattajien lausunnot ovat kiistanalaisia ja jotkut niistä ovat selvästi vanhentuneita, voidaan yleisesti ottaen päätellä:
Stephen Zeigerin artikkelissa Rational Software Corporationista [29] väitetään, että kehitys Adassa on yleensä 60 % halvempaa ja johtaa koodiin, jossa on 9 kertaa vähemmän vikoja kuin C:ssä. Vaikka näitä tuloksia ei voida siirtää suoraan C++:aan, ne ovat silti kiinnostavia, koska monet C++:n puutteet periytyvät C:stä.
Javaa ei voida pitää täydellisenä C++:n korvaajana, se on suunniteltu turvalliseksi kieleksi, jolla on alhainen pääsykynnys räätälöityjen sovellusten kehittämiseen, joilla on suuri siirrettävyys [30] , ja se on pohjimmiltaan sopimaton tietyntyyppisille C++:ssa kehitetyille sovelluksille. Java on kuitenkin laajuudessaan erittäin todellinen kilpailija C++:lle. Javan edut mainitaan yleensä seuraavasti:
Samaan aikaan roskakeräimen ja virtuaalikoneen käyttö luo rajoituksia, joita on vaikea ylittää. Java-ohjelmat ovat yleensä hitaampia, vaativat huomattavasti enemmän muistia, ja virtuaalikone eristää ohjelman käyttöjärjestelmästä, mikä tekee matalan tason ohjelmoinnin mahdottomaksi.
Empiirisessä tutkimuksessa [24] ei havaittu merkittävää eroa C++:n ja Javan kehitysnopeudessa. Tutkimus [26] osoitti myös, että ajatus merkittävästä erosta näiden kielien ohjelmien nopeuksissa ei aina pidä paikkaansa: kahdessa kolmesta testistä Java- ja C++-sovellusten nopeus osoittautui vertailukelpoinen. Samaan aikaan Java on ytimekkäämpi - ero koodin määrässä oli noin 10-15%.
Alkuperäinen C kehittyy edelleen, siinä kehitetään monia suuria projekteja: se on käyttöjärjestelmien kehittämisen pääkieli, siihen on kirjoitettu monien dynaamisten pelien pelimoottorit ja suuri määrä sovellussovelluksia. Useat asiantuntijat väittävät, että C:n korvaaminen C++:lla ei lisää kehittämisen tehokkuutta, vaan johtaa projektin tarpeettomaan monimutkaisuuteen, heikentää luotettavuutta ja nostaa ylläpitokustannuksia. Erityisesti:
Ei ole vakuuttavia todisteita siitä, että C++ on C:tä parempi ohjelmoijan tuottavuuden tai ohjelman ominaisuuksien suhteen. Vaikka on olemassa tutkimuksia [32] , joiden mukaan C-ohjelmoijat käyttävät noin 30-40 % kokonaiskehitysajasta (ilman virheenkorjausta) muistin hallintaan, mutta kun vertaillaan kehittäjien kokonaistuottavuutta [22] , C ja C++ ovat lähellä.
Matalan tason ohjelmoinnissa suuri osa C++:n uusista ominaisuuksista jää käyttökelvottomiksi lisääntyneen ylikuormituksen vuoksi: virtuaaliset toiminnot vaativat dynaamisen todellisen osoitteen laskennan (RVA), mallit johtavat koodin paisumiseen ja huonoihin optimointiominaisuuksiin, ajonaikainen kirjasto (RTL) on erittäin suuri, ja sen hylkääminen riistää suurimman osan C ++:n ominaisuuksista (jos vain siksi, että new/ toiminnot eivät ole käytettävissä delete). Tämän seurauksena ohjelmoijan on rajoituttava C:stä perittyihin toimintoihin, mikä tekee C ++:n käyttämisestä turhaa:
… ainoa tapa saada hyvä, tehokas, matalatasoinen, kannettava C++ on rajoittua kaikkiin asioihin, jotka ovat triviaalisti saatavilla C:ssä. Ja projektin rajaaminen C:hen tarkoittaa sitä, että ihmiset eivät heitä sitä roskiin ja että saatavilla on paljon ohjelmoijia, jotka todella ymmärtävät matalan tason ominaisuudet hyvin eivätkä hylkää niitä idioottimaisen "objektimallin" takia. hölynpöly.
… kun tehokkuus on ensiarvoisen tärkeää, C++:n "edut" ovat suuri virhe.
Eräässä kokeessa [22] komentosarja- ja toiminnalliset kielet, erityisesti Haskell , osoittivat 2-3-kertaisen lisäyksen ohjelmointiajassa ja koodin koossa verrattuna C++-ohjelmiin. Toisaalta C++-ohjelmat osoittautuivat yhtä paljon nopeammiksi. Kirjoittajat myöntävät, että heidän tietonsa eivät muodosta edustavaa otosta, ja pidättäytyvät tekemästä kategorisia johtopäätöksiä.
Toisessa kokeessa [34] tiukat toiminnalliset kielet ( Standard ML , OCaml ) osoittivat yleisen kehityksen kiihtymisen kertoimella 10 (johtuen pääasiassa virheiden varhaisesta havaitsemisesta) suunnilleen samanlaisilla suorituskykyindikaattoreilla (monet kääntäjät useissa tiloissa käytetty).
Lutz Preheltin [24] tutkimuksessa , joka perustui noin 80 vapaaehtoisten kirjoittaman ratkaisun käsittelyn tuloksiin, tehtiin erityisesti seuraavat johtopäätökset:
Useimmiten kriitikot eivät vastusta C++:aa mihinkään muuhun tiettyyn kieleen, vaan väittävät, että yksittäisen kielen käytön kieltäminen, jossa on lukuisia puutteita, puoltaa projektin hajottamista osatehtäviksi, jotka voidaan ratkaista eri kielillä, jotka soveltuvat parhaiten ne tekevät kehittämisestä huomattavasti vähemmän aikaa vievää ja parantavat ohjelmoinnin laatuindikaattoreita [35] [36] . Samasta syystä kritisoidaan yhteensopivuuden säilyttämistä C:n kanssa: jos tehtävän osa vaatii matalan tason ominaisuuksia, on järkevämpää erottaa tämä osa erilliseksi osajärjestelmäksi ja kirjoittaa se C:llä.
C ++:n kannattajat puolestaan väittävät, että kieltenvälisen vuorovaikutuksen teknisten ja organisatoristen ongelmien poistaminen käyttämällä yhtä universaalia kieltä useiden erikoistuneiden kielten sijaan on tärkeämpää kuin tämän universaalin kielen epätäydellisyydestä aiheutuvat menetykset, eli erittäin laaja C ++ -ominaisuussarja on tekosyy kunkin yksittäisen ominaisuuden puutteille; mukaan lukien C:stä perityt haitat ovat perusteltuja yhteensopivuuden eduilla (katso edellä ).
Näin ollen kannattajat pitävät samoja C ++:n ominaisuuksia - volyymi, monimutkaisuus, eklektisyys ja tietyn kohdealueen puute - " pääasiallisena etuna " ja kriitikot - " päähaittana ".
Kielen ideologia sekoittaa " käyttäytymisen hallinnan " " tehokkuuden hallintaan ": periaate " et maksa siitä, mitä et käytä " viittaa siihen, että ohjelmoijalle annetaan täydellinen hallinta ohjelman suorittamisen kaikista näkökohdista. melko alhainen taso on välttämätön ja riittävä ehto korkean koodin tehokkuuden saavuttamiseksi. Itse asiassa tämä ei päde mihinkään suuriin ohjelmiin: ohjelmoijan matalan tason optimoinnin pakottaminen, jonka laadukas verkkoaluekohtainen kielikääntäjä selvästikin pystyy suorittamaan tehokkaammin, johtaa vain koodin määrän kasvuun, ohjelmoinnin työvoimaintensiteetin kasvu ja koodin ymmärrettävyyden ja testattavuuden heikkeneminen. Siten periaate "älä maksa siitä, mitä ei käytetä" ei todellakaan tuota toivottuja hyötyjä tehokkuudessa, mutta vaikuttaa negatiivisesti laatuun.
Komponentti- ja olioohjelmointiAlan Kayn mukaan C++:ssa käytetty " Algol with classes" -objektimalli on huonompi kuin Objective-C :ssä käytetty "kaikki on objekti" [37] yleisen laajuuden, koodin uudelleenkäytön , ymmärrettävyyden, muunnettavuuden ja testattavuuden suhteen. .
C++-periytysmalli on monimutkainen, vaikeasti toteutettavissa oleva ja samalla provosoi monimutkaisten hierarkioiden muodostumista luokkien välisillä luonnottomilla suhteilla (esimerkiksi perinnöllinen sisäkkäisyyden sijaan). Tuloksena on tiiviisti yhdistettyjen luokkien luominen, joiden toiminnallisuus on epämääräisesti erotettu. Esimerkiksi [38] :ssa on opettava ja suositeltava esimerkki "lista"-luokan toteutuksesta "listaelementti"-luokan aliluokkana, joka puolestaan sisältää pääsytoiminnot muille listaelementeille. Tämä tyyppisuhde on matemaattisesti absurdi ja toistamaton tiukemmilla kielillä. Joidenkin kirjastojen ideologia vaatii manuaalista tyyppiä luokkahierarkiassa ylös ja alas ( static_castja dynamic_cast), mikä loukkaa kielen tyyppiturvallisuutta . C++-liuosten korkea viskositeetti saattaa vaatia suuria osia projektista kehittämään uudelleen pienin muutoksin myöhemmin kehitysprosessissa. Elävä esimerkki tällaisista ongelmista löytyy julkaisusta [35]
Kuten Ian Joyner [39] huomauttaa , C++ rinnastaa virheellisesti kapseloinnin (eli datan sijoittamisen objektien sisään ja toteutuksen erottamisen käyttöliittymästä) ja toteutuksen piilottamisen. Tämä vaikeuttaa pääsyä luokkatietoihin ja edellyttää, että sen käyttöliittymä toteutetaan lähes yksinomaan aksessoritoimintojen kautta (mikä puolestaan lisää koodin määrää ja monimutkaistaa sitä).
Tyyppivastaavuus C++:ssa määritellään tunnisteiden, ei allekirjoitusten tasolla. Tämä tekee mahdottomaksi vaihtaa rajapintojen sovitukseen perustuvia komponentteja, minkä vuoksi kirjastotasolla toteutettujen uusien toimintojen sisällyttäminen järjestelmään edellyttää olemassa olevan koodin manuaalista muokkaamista [40] . Kuten Linus Torvalds [33] huomauttaa , C++:ssa "koodi näyttää abstraktilta vain niin kauan kuin sitä ei tarvitse muuttaa."
C++:n kritiikki OOP:n näkökulmasta esitetään julkaisussa [39] .
MetaohjelmointiC++:n generatiivinen metaohjelmointi on malli- ja esiprosessoripohjaista , työvoimavaltaista ja laajuudeltaan rajoitettua. C++-mallinnusjärjestelmä on itse asiassa primitiivisen funktionaalisen ohjelmointikielen käännösaikainen muunnos. Tällä kielellä ei ole juurikaan päällekkäisyyttä itse C ++:n kanssa, minkä vuoksi potentiaali abstraktien monimutkaisuuden kasvuun on rajallinen. C++-malleja käyttävien ohjelmien ymmärrettävyys ja testattavuus on erittäin huono, ja mallien purkaminen itsessään tuottaa tehotonta koodia, koska mallin kieli ei tarjoa optimointikeinoja (katso myös osa #Laskennallinen tehokkuus ). Tällä tavalla toteutetut sulautetut toimialuekohtaiset kielet edellyttävät edelleen C++:n osaamista, mikä ei tarjoa täysimittaista työnjakoa. Näin ollen C++:n kyky laajentaa itse C++:n kykyjä on melko rajallinen [41] [42] .
Cross-platformKannettavan C++-koodin kirjoittaminen vaatii paljon taitoa ja kokemusta, ja "huolimaton" C++-koodi ei todennäköisesti ole kannettava [43] . Linus Torvaldsin mukaan C++:n kaltaisen siirrettävyyden saavuttamiseksi ohjelmoijan tulee rajoittua C++:n ominaisuuksiin, jotka on peritty C:stä [33] . Standardi sisältää monia "toteutusmääritetyiksi" määriteltyjä elementtejä (esimerkiksi luokkametodeihin osoittavien osoittimien koko vaihtelee eri kääntäjissä 4-20 tavua [44] ), mikä heikentää niitä käyttävien ohjelmien siirrettävyyttä.
Kielten standardoinnin direktiiviluonne , epätäydellinen taaksepäin yhteensopivuus ja standardin eri versioiden vaatimusten epäjohdonmukaisuus johtavat ongelmiin ohjelmien siirtämisessä eri kääntäjien ja jopa samojen kääntäjien versioiden välillä.
Kieli sisältää työkaluja, joiden avulla ohjelmoija voi rikkoa tietyssä tapauksessa annettua ohjelmoinnin kurinalaisuutta. Esimerkiksi modifioija constasettaa objektin tilan muuttumattomuuden ominaisuuden, mutta modifioija mutableon suunniteltu erityisesti pakottamaan lupa muuttaa tilaa const-objektin sisällä, toisin sanoen rikkoa konstenssirajoitusta. Lisäksi on sallittua dynaamisesti poistaa attribuutti constvakioobjektista ja muuttaa se L-arvoksi. Tällaisten ominaisuuksien esiintyminen kielessä tekee yrityksistä muodollisesti varmentaa koodia merkityksettömiä, ja rajoitusten käyttö optimointiin on mahdotonta.
Hallitsematon makrokorvausC-makrokorvaustoiminnot ( #define) ovat yhtä tehokkaita kuin vaarallisiakin. Ne säilyvät C++:ssa huolimatta siitä, että kaikkiin tehtäviin, joita varten ne tarjottiin C:ssä, C++ tarjosi tiukemmat ja erikoistuneet tilat - mallit, toimintojen ylikuormitus, rivin funktiot, nimitilat, edistyneempi kirjoittaminen, sovelluksen laajennus const-muokkaus , jne. C:stä perityissä standardikirjastoissa on monia mahdollisesti vaarallisia makroja [45] . Mallin metaohjelmointi yhdistetään joskus myös makrokorvauksen käyttöön ns. " syntaktinen sokeri ".
YlikuormitusongelmatC++:n toimintaperiaatteet ja operaattorin ylikuormitus johtavat merkittävään koodin päällekkäisyyteen. Alun perin tarkoituksena oli ottaa käyttöön niin kutsuttu " syntaktinen sokeri ", operaattorin ylikuormitus C++:ssa rohkaisee alkeisoperaattoreiden hallitsemattomaan käyttäytymiseen eri tyypeille. Tämä lisää dramaattisesti virheiden riskiä, varsinkin kun on mahdotonta ottaa käyttöön uutta syntaksia ja muuttaa olemassa olevaa (esimerkiksi luoda uusia operaattoreita tai muuttaa prioriteetteja tai assosiatiivisuutta), vaikka standardien C ++ -operaattoreiden syntaksi on riittävä Semantiikkaa ei suinkaan kaikista tyypeistä, jotka saattavat olla tarpeen sisällyttää ohjelmaan. Joitakin ongelmia aiheuttaa operaattorien / :n helppo ylikuormitus , mikä voi aiheuttaa erittäin salakavalia ja vaikeasti löydettäviä virheitä. Samaan aikaan C++:ssa ei suoriteta joitain intuitiivisesti odotettuja operaatioita (dynaamisten objektien puhdistus heittopoikkeuksien yhteydessä) ja merkittävä osa ylikuormitetuista funktioista ja operaattoreista kutsutaan implisiittisesti (tyyppivalu, luokkien tilapäisten esiintymien luominen jne. .). Tämän seurauksena työkalut, jotka alun perin oli tarkoitettu ohjelmien selkeyttämiseen sekä kehittämisen ja ylläpidon parantamiseen, ovat jälleen yksi tarpeettoman monimutkaisen ja epäluotettavan koodin lähde. newdelete
C++-mallien käyttö on parametrista polymorfiaa lähdekooditasolla, mutta käännettynä se muuttuu ad hoc -polymorfisiksi (eli toimintojen ylikuormitukseksi), mikä johtaa konekoodin määrän merkittävään kasvuun verrattuna kieliin, joilla on todellinen polymorfinen tyyppinen järjestelmä ( ML :n jälkeläiset ). Konekoodin koon pienentämiseksi he yrittävät käsitellä lähdekoodia automaattisesti ennen mallien purkamisvaihetta [46] [47] . Toinen ratkaisu voisi olla mallien vientimahdollisuus, joka standardisoitiin jo vuonna 1998, mutta se ei ole saatavilla kaikissa kääntäjissä, koska sitä on vaikea toteuttaa [48] [49] [mielipiteitä 4] ja C ++ -mallikirjastojen tuontia. kielille, joilla on huomattavasti erilainen C++ semantiikka, se olisi silti hyödytöntä. C++:n kannattajat kiistävät koodin paisumisen laajuuden liioitelluksi [50] , vaikka jättäisivät huomioimatta sen tosiasian, että C:ssä parametrinen polymorfismi käännetään suoraan, toisin sanoen ilman funktiokappaleiden kopioimista. Samaan aikaan C++:n kannattajat uskovat, että parametrinen polymorfismi C:ssä on vaarallista – toisin sanoen vaarallisempaa kuin siirtyminen C:stä C++:aan (C++:n vastustajat väittävät päinvastaista - katso edellä).
OptimointipotentiaaliHeikosta tyyppijärjestelmästä ja sivuvaikutusten runsaudesta johtuen ohjelmien samanarvoinen muuntaminen on erittäin vaikeaa, ja siksi kääntäjälle upotetaan monia optimoivia algoritmeja, kuten ohjelmien automaattinen rinnakkaisu , yleisten osalausekkeiden poistaminen , λ-nosto, kutsut menettelyt jatkosyötöllä , superkäännöksellä jne. Tämän seurauksena C++-ohjelmien todellista tehokkuutta rajoittavat ohjelmoijien taidot ja tiettyyn projektiin sijoitetut ponnistelut, ja "huolimaton" toteutus voi olla teholtaan huomattavasti huonompi kuin "huolimaton" ” toteutuksia korkeamman tason kielillä, mikä on vahvistettu kielten vertailutesteillä [34] . Tämä on merkittävä este C++:n käytölle tiedonlouhintateollisuudessa .
Tehokas muistinhallintaVastuu tehokkaasta muistinhallinnasta on kehittäjän harteilla ja riippuu kehittäjän taidoista. Automaattista muistinhallintaa varten C ++:ssa ns. "älykkäät osoittimet", manuaalinen muistinhallinta vähentää ohjelmoijien itsensä tehokkuutta (katso osio Tehokkuus ) . Useat roskienkeruun toteutukset , kuten staattinen alueiden päättely , eivät sovellu C++-ohjelmiin (tarkemmin sanottuna tämä edellyttää uuden kielitulkin käyttöönottoa C++-kielen päälle, joka on hyvin erilainen kuin C++ molemmissa objektiivisissa ominaisuuksissa ja yleinen ideologia), koska tarve saada suora pääsy AST :iin .
Suorituskykytekijöiden korrelaatio kehityskustannuksiin sekä ohjelmointiyhteisössä viljelty yleinen kurinalaisuus ja ohjelmointikulttuuri ovat tärkeitä asiakkaille, jotka valitsevat kielen (ja vastaavasti suosivat tätä kehittäjien kieltä) projektiensa toteuttamiseen, sekä ihmisille, jotka alkavat oppia ohjelmointia, erityisesti tarkoituksenaan ohjelmoida omiin tarpeisiisi.
Ohjelmoinnin laatu ja kulttuuriC++:n periaate " ei määrätä" hyvää "ohjelmointityyliä " on vastoin teollista ohjelmointilähestymistapaa, jossa johtava rooli on ohjelmiston laadulla ja mahdollisuudella ylläpitää koodia paitsi kirjoittajan toimesta. , ja mitkä kielet, jotka minimoivat inhimillisen tekijän vaikutuksen, ovat suositeltavia eli vain " hyvän ohjelmointityylin määräämistä ", vaikka tällaisilla kielillä voi olla korkeampi pääsykynnys.
On olemassa mielipide, että suositus C++:n käyttöön (mahdollisuudella valita vaihtoehtoisia kieliä) luonnehtii kielteisesti ohjelmoijan ammatillisia ominaisuuksia. Erityisesti Linus Torvalds sanoo käyttävänsä ehdokkaiden myönteisiä mielipiteitä C++:sta keskeyttämiskriteerinä [mielipiteitä 3] :
C++ on kauhea kieli. Vielä kauheammaksi tekee se, että monet alilukutaitoiset ohjelmoijat käyttävät sitä... Suoraan sanottuna, vaikka ei ole muuta syytä valita C:tä kuin pitää C++-ohjelmoijat loitolla, se yksinään olisi tarpeeksi hyvä syy käyttää sitä. C.
…Olen tullut siihen johtopäätökseen, että haluaisin todellakin mieluummin potkaista pois kaikki, jotka haluavat kehittää projektin C++:n sijaan C:n sijaan, jotta tämä henkilö ei pilaa projektia, jossa olen mukana.
Kielen jatkuva kehitys rohkaisee (ja joskus pakottaa) ohjelmoijia vaihtamaan jo virheenkorjattua koodia yhä uudelleen - tämä ei ainoastaan lisää kehityskustannuksia, vaan sisältää myös riskin, että virheenkorjauskoodiin tulee uusia virheitä. Erityisesti, vaikka taaksepäin yhteensopivuus C:n kanssa oli alun perin yksi C++:n ydinperiaatteista, vuodesta 1999 lähtien C on lakannut olemasta C++:n osajoukko, joten virheenkorjattua C-koodia ei voi enää käyttää C++-projektissa ilman muutoksia.
Monimutkaisuus itsensä vuoksiSen apologeetit määrittelevät C++:n "voimakkaimmaksi" juuri siksi , että se on täynnä vaarallisia, keskenään ristiriitaisia piirteitä. Eric Raymondin mukaan tämä tekee itse kielestä perustan ohjelmoijien henkilökohtaiselle itsensä vahvistamiselle, mikä tekee kehitysprosessista itsetarkoituksen:
Ohjelmoijat ovat usein loistokkaita yksilöitä, jotka ovat ylpeitä... kyvystään käsitellä monimutkaisuutta ja abstraktioita taitavasti. Usein he kilpailevat keskenään yrittäen selvittää, kuka voi luoda "monimutkaisimpia ja kauneimpia monimutkaisuuksia". ... kilpailijat uskovat, että heidän on kilpailtava muiden ihmisten "koristeiden" kanssa lisäämällä omansa. Melko pian "massiivisesta kasvaimesta" tulee alan standardi, ja kaikilla on käynnissä suuria, bugisia ohjelmia, joita edes niiden tekijät eivät voi tyydyttää.
…
… tämä lähestymistapa voi joutua vaikeuksiin, jos ohjelmoijat tekevät yksinkertaisia asioita monimutkaisilla tavoilla yksinkertaisesti siksi, että he tietävät ne ja osaavat käyttää niitä.
On havaittu tapauksia, joissa huolimattomat ohjelmoijat, käyttämällä C ++:n vahvaa kontekstiriippuvuutta ja kääntäjän makromääritelmien jäljittämiskyvyn puutetta, hidastivat projektin kehitystä kirjoittamalla yhden tai kaksi ylimääräistä, kääntäjän näkökulmasta oikein. näkökulmasta, koodirivejä, mutta tuodaan heidän kustannuksellaan käyttöön vaikeasti havaittava spontaanisti ilmennyt virhe. Esimerkiksi:
#define if(a) if(rand())Kielellä , joiden oikeellisuus on todistettu , on mahdotonta tehdä vahinkoa tällä tavalla, jopa edistyneillä makrotoiminnoilla.
Epäluotettava tuoteKohtuuton sivuvaikutusten runsaus yhdistettynä kielen ajonaikaisen järjestelmän hallinnan puutteeseen ja heikon tyyppiseen järjestelmään tekee C++ -ohjelmista alttiita arvaamattomille kohtalokkaille kaatumisille (tunnetut kaatumiset viesteillä, kuten "Pääsyhäiriö", "Puhas virtuaalinen toiminto" call" tai "Ohjelma suoritti laittoman toiminnon ja suljetaan"), mikä sulkee pois C ++:n käytön, jolla on korkeat vikasietovaatimukset. Lisäksi se pidentää itse kehitysprosessin kestoa [34] .
ProjektinhallintaYllä luetellut tekijät tekevät C++-projektinhallinnan monimutkaisuudesta yhden ohjelmistokehitysalan suurimmista.
James Coggins, The C++ Reportin
nelivuotinen kolumnisti , selittää:
Ongelmana on, että OOP-ohjelmoijat ovat kokeilleet insestisovelluksia ja pyrkineet alhaiseen abstraktiotasoon. He esimerkiksi rakensivat luokkia, kuten "linkitetty lista" "käyttöliittymän" tai "säteilysäteen" tai "äärellisten elementtien mallin" sijaan. Valitettavasti vahva tyyppitarkistus, joka auttaa C++-ohjelmoijia välttämään virheitä, vaikeuttaa myös suurten objektien rakentamista pienistä.
Ainoa C++: n suora jälkeläinen on D-kieli , joka on tarkoitettu C++:n uudelleenmuokkaukseen sen ilmeisimpien ongelmien ratkaisemiseksi. Kirjoittajat luopuivat yhteensopivuudesta C:n kanssa, säilyttäen syntaksin ja monet C ++:n perusperiaatteet ja tuoneet kieleen uusia kieliä ominaisia piirteitä. D:llä ei ole esiprosessoria, ei otsikkotiedostoja, ei useita perintöjä, mutta moduulijärjestelmä, rajapinnat, assosiatiiviset taulukot, tuki merkkijonoissa olevalle unicodelle , roskien kerääminen (säilyttäen samalla mahdollisuus manuaaliseen muistinhallintaan), sisäänrakennettu monisäikeisyys, tyyppipäätelmä , puhtaiden funktioiden ja muuttumattomien arvojen eksplisiittinen ilmoitus. D:n käyttö on hyvin rajallista, eikä sitä voida pitää C ++:n todellisena kilpailijana.
C++:n vanhin kilpailija matalan tason tehtävissä on Objective-C , joka on myös rakennettu periaatteelle yhdistää C objektimalliin, vain objektimalli periytyy Smalltalkista . Objective-C:tä, kuten sen jälkeläistä Swiftiä , käytetään laajasti ohjelmistokehitykseen macOS:lle ja iOS:lle.
Yksi ensimmäisistä vaihtoehdoista C++:lle sovellusohjelmoinnissa oli Java-kieli . Sitä pidetään usein virheellisesti C++:n suorana jälkeläisenä; Itse asiassa Javan semantiikka periytyy Modula-2- kielestä , ja C++:n perussemantiikkaa ei voida jäljittää Javassa. Tämän ja kielten sukututkimuksen perusteella (Modula-2 on Simulan jälkeläinen , kuten C++, mutta se ei ole C), Javaa kutsutaan oikeammin C++:n " toiseksi serkkuksi " eikä " perijäksi ". Sama voidaan sanoa C# -kielestä , vaikka affiniteettiprosentti C++:n kanssa on hieman korkeampi kuin Javalla.
Yritys yhdistää Java:n ja C#:n turvallisuus ja kehitysnopeus C++:n ominaisuuksiin oli Managed C++ -murte (myöhemmin C++/CLI ). Microsoft on kehittänyt sen ensisijaisesti siirtämään olemassa olevia C++-projekteja Microsoftin .NET-alustalle. Ohjelmat toimivat CLR :n alaisina ja voivat käyttää kaikkia .NET-kirjastoja, mutta C++-ominaisuuksien käyttöön liittyy useita rajoituksia, mikä vähentää C++:n tehokkaasti C#:ksi. Tämä murre ei ole saanut laajaa tunnustusta, ja sitä käytetään pääasiassa linkittämään puhtaalla C ++ -kielellä kirjoitettuja kirjastoja C # -sovelluksiin.
Vaihtoehtoinen tapa kehittää C-kieli on yhdistää sitä ei olio-ohjelmointiin, vaan applikatiiviseen ohjelmointiin , toisin sanoen parantaa matalan tason ohjelmien abstraktiota, tarkkuutta ja modulaarisuutta tarjoamalla ennustettavaa käyttäytymistä ja viittauksen läpinäkyvyyttä . Esimerkkejä tämänsuuntaisesta työstä ovat kielet BitC , Cyclone ja Limbo . Vaikka FP:tä on myös onnistuttu käyttämään reaaliaikaisissa ongelmissa ilman integraatiota C-työkalujen kanssa [52] [53] [54] , vielä tällä hetkellä (2013) matalan tason kehityksessä C-työkalujen käyttö jossain määrin sillä on parempi työvoimaintensiteetin ja tehokkuuden suhde. Python- ja Lua -kehittäjät ovat tehneet paljon työtä Pythonissa ja Luassa varmistaakseen, että C++-ohjelmoijat käyttävät näitä kieliä, joten kaikista FP:lle läheisesti liittyvistä kielistä ne ovat yleisimpiä. todettiin käytettävän yhdessä C++:n kanssa samassa projektissa. Merkittävimmät kosketuskohdat C++:n ja FP:n välillä ovat C++:ssa kehitettyjen wxWidgets- ja Qt -kirjastojen sidokset C++-spesifisellä ideologialla Lispiin , Haskelliin ja Pythoniin (useimmissa tapauksissa sidokset toiminnallisiin kieliin tehdään kirjastoille, jotka on kirjoitettu kielellä C tai muut toiminnalliset kielet).
Toinen C++:n kilpailijana pidetty kieli on Nemerle , joka on seurausta yrityksestä yhdistää Hindley-Milnerin kirjoitusmalli ja Common Lispin makroalajoukko C#:n kanssa [55] . Samaan tapaan on Microsoftin F# , ML : n murre , joka on sovitettu .NET-ympäristöön.
Googlen vuonna 2009 kehittämä Go - ohjelmointikieli oli yritys luoda teollinen korvaava C / C + + : lle . Kielen kirjoittajat huomauttavat suoraan, että sen luomisen motiivina olivat C- ja C++-kielten erityispiirteistä johtuvat kehitysprosessin puutteet [56] . Go on kompakti, mutkaton pakottava kieli C:n kaltaisella syntaksilla, ilman esiprosessoria, staattista kirjoitusta, vahvaa kirjoitusta, pakkausjärjestelmää, automaattista muistinhallintaa, joitakin toiminnallisia ominaisuuksia, taloudellisesti rakennettu OOP-alijärjestelmä ilman täytäntöönpanon periytymistä, mutta jossa on liitännät ja ankkakirjoitus , sisäänrakennettu monisäikeistys, joka perustuu korutiineihin ja putkiin (a-la Occam ). Kieli on sijoitettu vaihtoehdoksi C ++:lle, eli ennen kaikkea välineeksi erittäin monimutkaisten erittäin monimutkaisten laskentajärjestelmien ryhmäkehitykseen, mukaan lukien hajautetut, mahdollistaen tarvittaessa matalan tason ohjelmoinnin.
Samassa ekologisessa markkinarakossa C/C++:n kanssa on vuonna 2010 kehittämä ja Mozilla Corporationin ylläpitämä Rust, joka keskittyy turvalliseen muistinhallintaan ilman roskakeräilijää . Erityisesti Microsoft ilmoitti vuonna 2019 suunnitelmista korvata C / C ++ osittain Rustilla [57] .
![]() | ||||
---|---|---|---|---|
|
Ohjelmointikielet | |
---|---|
|
ISO- standardit | |
---|---|
| |
1-9999 _ _ |
|
10 000 - 19999 |
|
20 000+ | |
Katso myös: Luettelo artikkeleista, joiden otsikot alkavat sanalla "ISO" |
C++ | |
---|---|
Erikoisuudet | |
Jotkut kirjastot | |
Kääntäjät | |
vaikutti | |
|