C++ | |
---|---|
Szemantika | több paradigma : objektumorientált , általános , procedurális , metaprogramozás |
Nyelvóra | objektum-orientált programozási nyelv , többparadigmás programozási nyelv , procedurális programozási nyelv , funkcionális programozási nyelv , általános programozási nyelv , programozási nyelv , szabad formátumú nyelv [d] és fordított programozási nyelv |
A végrehajtás típusa | összeállított |
Megjelent | 1983 |
Szerző | Stroustrup, Bjorn |
Fájlkiterjesztés _ | .cc, .cpp, .cxx, .c, .c++, .h, .hpp, .hh, .hxxvagy.h++ |
Kiadás | |
Típusrendszer | statikus |
Főbb megvalósítások | GNU C++ , Microsoft Visual C++ , Intel C++ fordító , Open64 C++ fordító , Clang , Comeau C/C++ , Embarcadero C++ Builder , Watcom C++ fordító , Digital Mars C++, Oracle Solaris Studio C++ Ci+ |
Dialektusok | ISO/IEC 14882 C++ |
Befolyásolva | C , Simula , Algol 68 , Clu , ML és Ada |
Weboldal | isocpp.org _ |
Médiafájlok a Wikimedia Commons oldalon |
A C ++ (ejtsd: c-plus-plus [2] [3] ) egy lefordított , statikusan tipizált , általános célú programozási nyelv .
Támogatja az olyan programozási paradigmákat , mint a procedurális programozás , az objektum-orientált programozás , az általános programozás . A nyelv gazdag szabványkönyvtárral rendelkezik, amely általános konténereket és algoritmusokat , I/O-t, reguláris kifejezéseket, többszálú támogatást és egyebeket tartalmaz. A C++ egyesíti a magas és az alacsony szintű nyelvek jellemzőit [4] [5] . Elődjéhez - a C nyelvhez - képest a legnagyobb figyelmet az objektum-orientált és általános programozás támogatására fordítják [5] .
A C++- t széles körben használják szoftverfejlesztésre, mivel az egyik legnépszerűbb programozási nyelv [vélemények 1] [vélemények 2] . Alkalmazási körébe tartozik operációs rendszerek , különféle alkalmazásprogramok, eszközillesztő -programok, beágyazott rendszerekhez való alkalmazások, nagy teljesítményű szerverek és számítógépes játékok létrehozása. A C++ nyelvnek számos megvalósítása létezik, ingyenesen és kereskedelmileg is, valamint különféle platformokra. Például az x86 platformon ezek a GCC , Visual C++ , Intel C++ Compiler , Embarcadero (Borland) C++ Builder és mások. A C++ óriási hatással volt más programozási nyelvekre, különösen a Java -ra és a C# -ra .
A C++ szintaxis a C nyelvből öröklődik . Az egyik eredeti tervezési elv a C-vel való kompatibilitás fenntartása volt. A C++ azonban nem szigorúan a C szuperhalmaza; A C és C++ fordítók által egyformán jól lefordítható programok készlete meglehetősen nagy, de nem tartalmazza az összes lehetséges C programot .
A fejlődés történelmi szakasza [6] | Év |
---|---|
BCPL nyelv | 1966 |
A B nyelv (a Thompson eredeti fejlesztése UNIX alatt ) | 1969 |
C nyelv | 1972 |
C osztályokkal | 1980 |
C84 | 1984 |
Cfront (E kiadás) | 1984 |
cfront (1.0-s kiadás) | 1985 |
Többszörös/virtuális öröklődés | 1988 |
Általános programozás ( sablonok ) | 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 |
A nyelv az 1980-as évek elején keletkezett , amikor a Bell Labs alkalmazottja, Björn Stroustrup számos fejlesztést dolgozott ki a C nyelven saját igényei szerint [7] . Amikor Stroustrup az 1970 -es évek végén a Bell Labs-nál kezdett dolgozni a sorbanálláselmélet problémáin (a telefonhívások modellezésére alkalmazva), úgy találta, hogy az akkoriban létező modellezési nyelvek használatára tett kísérletek nem voltak hatékonyak, és a rendkívül hatékony gépi nyelvek használata. túl nehéz volt a korlátozott kifejezőképességük miatt. Például a Simula nyelv olyan tulajdonságokkal rendelkezik, amelyek nagy szoftverek fejlesztéséhez nagyon hasznosak lennének, de túl lassú, a BCPL nyelv pedig elég gyors, de túl közel áll az alacsony szintű nyelvekhez, és nem alkalmas nagy szoftverek fejlesztésére.
Felidézve a disszertáció tapasztalatait, Stroustrup úgy döntött, hogy a C nyelvet (a BCPL utódját) kiegészíti a Simula nyelvben elérhető képességekkel. A C nyelv, amely a UNIX rendszer alapnyelve, amelyen a Bell számítógépek futottak, gyors, funkciókban gazdag és hordozható. Stroustrup hozzáadta az osztályokkal és objektumokkal való munka képességét. Ennek eredményeként a gyakorlati modellezési feladatok elérhetőnek bizonyultak mind a fejlesztési idő (a Simula-szerű osztályok használata miatt), mind a számítási idő (a C sebessége miatt) tekintetében. A C első kiegészítései az osztályok ( beágyazással ), az osztályöröklés, a szigorú típusellenőrzés, a soron belüli függvények és az alapértelmezett argumentumok voltak . A nyelv korai verziói, amelyeket eredetileg "C with classes"-nek hívtak, az 1980-as évek óta elérhetők .
A C osztályokkal való fejlesztése közben Stroustrup megírta a cfront programot , egy olyan fordítót , amely a C forráskódot osztályokkal sima C forráskódra dolgozza át. Ez lehetővé tette számunkra, hogy egy új nyelven dolgozzunk, és a gyakorlatban is használhassuk a UNIX-ban már elérhető infrastruktúra felhasználásával. fejlesztés C. Egy új nyelv, a szerző számára váratlanul, nagy népszerűségre tett szert a kollégák körében, és hamarosan Stroustrup már nem tudta személyesen támogatni, több ezer kérdésre válaszolt.
1983 - ra új funkciókkal bővült a nyelv, mint például a virtuális függvények, a funkciók és operátorok túlterhelése, hivatkozások, konstansok, a szabad memóriakezelés felhasználói vezérlése, továbbfejlesztett típusellenőrzés és új megjegyzésstílus ( //). Az eredményül kapott nyelv már nem csak a klasszikus C kiterjesztett változata, és C-ről osztályokkal átnevezték "C++"-ra. Első kereskedelmi forgalomba hozatalára 1985 októberében került sor .
A hivatalos szabványosítás megkezdése előtt a nyelvet főleg a Stroustrup fejlesztette ki a programozói közösség kérésére. A szabványos nyelvi leírások funkcióját Stroustrup C ++ nyelvű nyomtatott munkái látták el (a nyelv leírása, kézikönyv stb.). Csak 1998 - ban ratifikálták a C++ nyelv nemzetközi szabványát: ISO/IEC 14882:1998 "Standard for the C++ Programming Language"; a szabvány technikai korrekcióinak 2003 -as elfogadását követően ennek a szabványnak a következő változata az ISO/IEC 14882:2003 [8] .
1985- ben jelent meg a The C++ Programming Language első kiadása , amely a nyelv első leírását adta, ami a hivatalos szabvány hiánya miatt rendkívül fontos volt. 1989 - ben adták ki a C++ 2.0-s verzióját. Új funkciói közé tartozik a többszörös öröklődés, az absztrakt osztályok, a statikus tagfüggvények, az állandó függvények és a védett tagok. 1990 -ben jelent meg a "Commented Reference Guide to C++", amely később a szabvány alapja lett. A legutóbbi frissítések sablonokat, kivételeket, névtereket, új castokat és logikai típust tartalmaztak. Az Alexander Stepanov és Meng Li által kifejlesztett Standard Template Library-t (STL) választották az általános algoritmusok tárolásának és elérésének alapjául .
A C++ Standard Library is vele együtt fejlődött. A C++ szabványos könyvtárának első kiegészítése az I/O adatfolyam volt, amely lehetőséget biztosított a hagyományos C printfés scanf. Később a standard könyvtár legjelentősebb fejlesztése a Standard Template Library felvétele volt .
A C++ folyamatosan fejlődik, hogy megfeleljen a modern követelményeknek. A C ++ nyelvet fejlesztő és a C ++ szabványosítási bizottságnak javaslatokat küldő csoportok egyike a Boost , amely többek között a nyelv képességeinek fejlesztésével foglalkozik metaprogramozási funkciók hozzáadásával .
A C++ nyelvhez senki nem rendelkezik jogokkal, az ingyenes. Maga a nyelvi szabványdokumentum azonban (a tervezetek kivételével) nem elérhető szabadon [10] . A szabványosítási folyamat részeként az ISO többféle kiadványt készít. A műszaki jelentéseket és műszaki leírásokat különösen akkor teszik közzé, amikor "a jövő látható, de nincs azonnali lehetőség a nemzetközi szabvány közzétételére vonatkozó megállapodásra". 2011-ig három technikai jelentés jelent meg a C++-ról: TR 19768: 2007 (más néven C++ Technical Report 1) a főként a C++11-be integrált könyvtárbővítésekről, a TR 29124: 2010 a speciális matematikai függvényekről és a TR 24733: 2011. tizedes lebegőpontos aritmetika. Műszaki specifikáció DTS 18822:. A 2014-et (fájlrendszer szerint) 2015 elején hagyták jóvá, a többi specifikáció fejlesztés alatt áll, és jóváhagyásra vár [11] .
2016 márciusában Oroszországban létrehozták a WG21 C++ munkacsoportot . A csoport a C++ szabványra vonatkozó javaslatok összegyűjtése, a bizottság elé terjesztése és a Nemzetközi Szabványügyi Szervezet (ISO) közgyűlésein való megvédése céljából jött létre [12] .
Az eredményül kapott nyelvnév a C unary postfix increment++ operátorból származik (egy változó értékét eggyel növelve). A C+ nevet nem használtuk, mert ez egy szintaktikai hiba a C nyelvben, ráadásul a nevet egy másik nyelv vette fel. A nyelvet azért sem nevezték D-nek, mert " a C kiterjesztése, és nem próbálja meg megoldani a problémákat a C elemek eltávolításával " [7] .
A The Design and Evolution of C++ [13] című könyvében Bjorn Stroustrup leírja azokat az elveket, amelyeket a C++ tervezésekor követett. Ezek az alapelvek megmagyarázzák, hogy a C++ miért olyan, amilyen. Néhány közülük:
A C++ szabvány két fő részből áll: az alapnyelv leírásából és a szabványkönyvtár leírásából.
A nyelv eleinte a formális kereteken kívül, spontán módon, az előtte álló feladatoknak megfelelően fejlődött. A nyelv fejlődését a cfront keresztfordító fejlesztése kísérte . A nyelvi újítások a keresztfordító verziószámának változásában is megmutatkoztak. Ezek a keresztfordító verziószámok magára a nyelvre is kiterjedtek, de a C++ verziókról jelenleg nincs szó. Csak 1998-ban vált szabványossá a nyelv.
A névtelen névtér speciális eset. A benne leírt összes név csak az aktuális fordítási egységben érhető el, és helyi kötéssel rendelkezik. A névtér stdtartalmazza a szabványos C++ könyvtárakat.
A következő beépített típusok érhetők el C++ nyelven. A C++ típusok szinte azonosak a C adattípusokkal :
Az összehasonlító operátorok visszatérési típusa bool. ifA , utáni zárójelben lévő kifejezések [14]while típusúvá alakulnak . bool
A nyelv bevezette a referenciák fogalmát, a C++11 szabványból pedig az rvalues - references és a forwarding references . (Lásd link (C++) )
A C++ objektumorientált funkciókat ad a C-hez. Olyan osztályokat mutat be, amelyek az OOP három legfontosabb tulajdonságát biztosítják : a beágyazást , az öröklődést és a polimorfizmust .
A C++ szabványban az osztály egy felhasználó által definiált típus, amelyet a vagy kulcsszavak egyikével deklarálnak class, structa unionstruktúra a struct, az unió pedig a union. A használt kulcsszótól függően magának az osztálynak bizonyos tulajdonságai is megváltoznak. Például a -val deklarált osztályban structa manuálisan hozzárendelt hozzáférés-módosítóval nem rendelkező tagok alapértelmezés szerint nyilvánosak, nem pedig privátak.
Az osztálydefiníció törzsében megadhatja a függvénydeklarációkat és azok definícióját is. Ez utóbbi esetben a függvény inline ( inline). A nem statikus tagfüggvények rendelkezhetnek constés minősítőkkel volatile, valamint referenciaminősítővel ( &vagy &&).
A C++ támogatja a többszörös öröklődést . Az alaposztályok (ősosztályok) az osztálydeklaráció fejében vannak megadva, esetleg hozzáférési specifikációkkal. Az egyes osztályokból származó öröklődés lehet nyilvános, védett vagy privát:
Az alaposztály tagjainak hozzáférési/öröklési módja | magántag | védett tagja | közéleti tag |
---|---|---|---|
magánörökség | nem elérhető | magán | magán |
védett-öröklés | nem elérhető | védett | védett |
közörökség | nem elérhető | védett | nyilvános |
Alapértelmezés szerint az alaposztály privátként öröklődik.
Az öröklődés eredményeként a gyermekosztály megkapja az ősosztályok összes mezőjét és azok összes metódusát; azt mondhatjuk, hogy a leszármazott osztály minden példánya tartalmazza az egyes ősosztályok egy-egy részpéldányát . Ha egy ősosztály többször öröklődik (ez akkor lehetséges, ha a létrehozandó osztály több alaposztályának őse), akkor a leszármazott osztály példányai ennek az ősosztálynak annyi alpéldányát tartalmazzák majd. Ennek elkerülésére, ha nem kívánatos, a C++ támogatja a virtuális öröklődés koncepcióját . Örökléskor az alaposztály virtuálissá nyilvánítható; az ősosztály minden virtuális előfordulására a leszármazott osztály öröklési fájában csak egy részpéldány jön létre a leszármazottban.
A C++ támogatja a dinamikus polimorfizmust és a parametrikus polimorfizmust .
A paraméteres polimorfizmust a következők képviselik:
A dinamikus polimorfizmust virtuális módszerekkel és öröklődési hierarchiával valósítják meg. A C++ nyelvben egy típus akkor polimorf, ha rendelkezik legalább egy virtuális metódussal. Példa a hierarchiára:
osztály ábra { nyilvános : virtuális üresség Draw () = 0 ; // tiszta virtuális metódus virtual ~ ábra (); // ha van legalább egy virtuális metódus, a destruktort virtuálissá kell tenni }; osztály Négyzet : közfigura _ { nyilvános : void Draw () felülbírálás ; }; osztály Kör : közfigura _ { nyilvános : void Draw () felülbírálás ; };Itt a Figure osztály absztrakt (és még interfész osztály is ), mivel a Draw metódus nincs definiálva. Az osztályba tartozó objektumok nem hozhatók létre, de használhatók az ábra típusú hivatkozások vagy mutatók. A Draw metódus megvalósításának kiválasztása futási időben történik az objektum tényleges típusa alapján.
A C++ nyelven a beágyazás az osztálytagok hozzáférési szintjének megadásával valósul meg: nyilvánosak (public, public), védettek ( protected) és privátak (privát, private). A C++-ban a struktúrák formálisan csak abban különböznek az osztályoktól, hogy alapértelmezés szerint egy struktúra esetében az osztálytagokhoz való hozzáférési szint és az öröklődés típusa nyilvános, míg egy osztály esetében privát.
Hozzáférés | magán | védett | nyilvános |
---|---|---|---|
Maga az osztály | Igen | Igen | Igen |
Barátok | Igen | Igen | Igen |
Örökösök | Nem | Igen | Igen |
Kívülről | Nem | Nem | Igen |
A hozzáférés ellenőrzése fordítási időben történik, a hozzáférhetetlen osztálytag elérésének megkísérlése fordítási hibát okoz.
BarátokA barátfüggvények olyan függvények, amelyek nem tagfüggvények, és mégis hozzáférnek az osztály védett és privát tagjaihoz. Ezeket az osztály törzsében a következőképpen kell megadni friend. Például:
osztály Mátrix { barát Matrix Multiply ( Mátrix m1 , Mátrix m2 ); };Itt a függvény Multiplyelérheti a . bármely mezőjét és tagfüggvényét Matrix.
Mind az egész osztály, mind az osztály egy tagfüggvénye barátnak nyilvánítható. A baráti kapcsolatok négy fontos korlátozása a C++ nyelven:
Általában ez a szabály a következőképpen fogalmazható meg: "A baráti kapcsolat csak azon osztályok (osztály és funkció) között létezik, amelyekre a kódban kifejezetten deklarálva van, és csak abban az irányban hat, amelyben deklarálják."
Egy alapértelmezett osztálynak hat speciális funkciója lehet: alapértelmezett konstruktor, másolás konstruktor, mozgatási konstruktor, destruktor, másolási hozzárendelés operátor, áthelyezési hozzárendelés operátor. Lehetőség van mindegyiket kifejezetten meghatározni (lásd a három szabályt ).
class Array { nyilvános : Tömb ( ) = alapértelmezett // a fordító létrehozza magának az Array alapértelmezett konstruktorát ( size_t _len ) : len ( _len ) { val = új dupla [ _len ]; } Array ( const Array & a ) = törlés ; // a konstruktor másolása kifejezetten eltávolítva Tömb ( Tömb && a ); // konstruktor áthelyezése ~ Array () { törlés [] val ; } Tömb & operátor = ( const Tömb & rhs ); // hozzárendelés operátor másolása Array & operator = ( Tömb && rhs ); // hozzárendelés áthelyezése operátor double & operator []( size_t i ) { return val [ i ]; } const double & operátor []( size_t i ) const { return val [ i ]; } védett : std :: méret_t len = 0 ; // mező inicializálása double * val { nullptr }; };A konstruktort az objektum (a megfelelő típusú) inicializálására hívják, amikor létrehozzák, a destruktort pedig az objektum megsemmisítésére. Egy osztálynak több konstruktora is lehet, de egy destruktornak csak egy. A C++-ban a konstruktorokat nem lehet virtuálisnak nyilvánítani, de a destruktorokat igen, és általában minden polimorf típusra deklarálják, hogy biztosítsák a hivatkozott vagy mutató által elérhető objektumok megfelelő megsemmisítését, függetlenül attól, hogy milyen típusú a hivatkozás vagy mutató. Ha legalább az egyik alaposztály rendelkezik virtuális destruktorral, akkor a gyermekosztály destruktora automatikusan virtuálissá válik.
A sablonok lehetővé teszik olyan függvények és osztályok létrehozását, amelyek egy adott típussal vagy értékkel vannak paraméterezve. Például az előző osztály bármilyen adattípushoz megvalósíthat egy tömböt:
sablon < típusnévT > _ class Array { ... T és operátor []( size_t i ) { return val [ i ]; } védett : std :: size_t len { 0 }; // mező inicializálása T * val { nullptr }; };A C++ Standard Library olyan eszközöket tartalmaz, amelyeknek a nyelv bármely implementációja számára elérhetőnek kell lenniük, hogy a programozók kényelmesen használhassák a nyelvi funkciókat, és alapot biztosítsanak az alkalmazások széles körének és a speciális könyvtárak fejlesztéséhez. A C++ Standard Library tartalmazza a C Standard Library egy részét. A C++ szabvány tartalmaz egy normatív hivatkozást az 1990 C szabványra , és nem határozza meg önállóan azokat a szabványos könyvtári funkciókat, amelyeket a C Standard Library-ből kölcsönöztek.
#includeA C++ szabványos könyvtár képességeihez való hozzáférést a megfelelő szabványos fejlécfájlok programba foglalása biztosítja (a direktíván keresztül ). Összesen 79 ilyen fájl van meghatározva a C++11 szabványban. A szabványos könyvtári szolgáltatások az std névtér részeként vannak deklarálva. A fejlécfájlok, amelyek neve megegyezik a „cX” mintával, ahol X a C Standard Library fejlécfájl neve kiterjesztés nélkül (cstdlib, cstring, cstdio stb.), a C Standard Library azon részének megfelelő deklarációkat tartalmaznak. szabványos könyvtári függvények is megtalálhatók a névtérben std.
A szabványos könyvtár a következő részeket tartalmazza:
A konténereket, karakterláncokat, algoritmusokat, iterátorokat és alapvető segédprogramokat – a C könyvtárból kölcsönzött kölcsönzések kivételével – együttesen STL-nek (Standard Template Library – szabványos sablonkönyvtár) nevezzük. Kezdetben ez a könyvtár külön termék volt, és a rövidítését másképp fejtették meg, de aztán integrált elemként bekerült a C ++ standard könyvtárba. Az elnevezés azt a tényt tükrözi, hogy az általánosított programozási mechanizmusokat (C++ templates - template) általános célú eszközök (tárolók, karakterláncok, algoritmusok) megvalósítására használják. Stroustrup írásai részletezik a választás okait. A legfontosabbak a választott megoldás nagyobb univerzálissága (a sablonkonténerek az objektumkonténerekkel ellentétben könnyen használhatók nem objektumtípusokhoz, és nem igényelnek közös őst az elemtípusokhoz) és a műszaki hatékonysága (általában sablonkonténer) a műveletek nem igényelnek virtuális függvényhívásokat, és könnyen beágyazhatók (inline), ami végső soron teljesítménynövekedést ad).
A C++11 szabvánnyal kezdve a következő szolgáltatások kerültek hozzáadásra:
Az STL, mielőtt belekerült a C++ szabványba, harmadik fél fejlesztése volt, először a HP , majd az SGI fejlesztése . A nyelvi szabvány nem nevezi "STL"-nek, mivel ez a könyvtár a nyelv szerves részévé vált, azonban sokan még mindig ezt a nevet használják, hogy megkülönböztessék a szabványos könyvtár többi részétől (I/O-folyamok ( iostream ), C alszakasz) és mások) .
Az SGI STL-en alapuló STLport [15] nevű projekt naprakészen tartja az STL, IOstream és karakterlánc osztályokat. Számos más projekt is fejleszti a szabványos könyvtár magáncélú felhasználását.
A C-t egy új programozási nyelv létrehozásának alapjául magyarázza, hogy a C nyelv:
A C nyelv számos jól ismert hiányossága ellenére Stroustrup ezt választotta alapként, mert "a C-nek megvannak a maga problémái, de a nulláról tervezett nyelvnek megvannak ezek, és ismerjük a C problémáit." Ezenkívül ez lehetővé tette számunkra, hogy gyorsan megszerezzük a fordító prototípusát ( cfront ), amely csak a hozzáadott szintaktikai elemeket fordította le az eredeti C nyelvre.
Ahogy a C++ fejlődött, más, a C konstrukciók képességeit felülíró funkciókat is beépítettek, és többször is felmerült a nyelvi kompatibilitás megszüntetésének kérdése az elavult konstrukciók eltávolításával. A kompatibilitás azonban megmaradt a következő okok miatt:
Az új C++ funkciók közé tartoznak a kifejezések deklarációi, függvénytípus-konverziók, operátorok newés delete, type bool, hivatkozások, kiterjesztett állandóság, soron belüli függvények, alapértelmezett argumentumok, felülírások, névterek, osztályok (beleértve az összes osztályhoz kapcsolódó szolgáltatást, mint az öröklődés, tagfüggvények, virtuális függvények, absztrakt osztályok és konstruktorok ), operátorfelülírások, sablonok, operátor ::, kivételkezelés, dinamikus azonosítás stb. A C++ nyelv sok esetben szigorúbb a típusellenőrzést illetően is, mint a C.
A C++ bevezette a dupla perjel megjegyzéseket ( //), amelyek a C elődjében, a BCPL -ben voltak .
constA C++ egyes funkciói később átkerültek C-be, mint például a és kulcsszavak, a ciklusdeklarációk inlineés a forC++-stílusú megjegyzések ( //). A C későbbi megvalósításai olyan funkciókat is bevezettek, amelyek nem találhatók meg a C++-ban, például makrókat va_argés továbbfejlesztett tömbparaméter-kezelést.
Míg a legtöbb C kód a C++-ra is érvényes, a C++ nem a C szuperkészlete, és nem is tartalmazza azt. Van olyan kód is, amely igaz a C-re, de nem igaz a C++-ra. Ez különbözteti meg az Objective C -től, amely egy másik C-javítás az OOP számára , amely csak a C szuperkészlete.
Vannak más különbségek is. Például a C++ nem engedi meg egy függvény meghívását main()programon belül, míg C-ben ez legális. Ezenkívül a C++ bizonyos szempontból szigorúbb; például nem teszi lehetővé a nem kapcsolódó mutatótípusok közötti implicit öntést, és nem engedélyezi a még nem deklarált függvényeket.
Ezenkívül a mindkét nyelvre érvényes kód eltérő eredményeket produkálhat attól függően, hogy melyik nyelv fordítójára van lefordítva. Például a legtöbb platformon a következő program "C" betűt ír ki, ha C fordító fordítja, és "C++" betűt, ha C++ fordító fordítja. Ennek az az oka, hogy a C karakterkonstansok (például 'a') típusúak int, a C++-ban viszont típusok char, és ezeknek a típusoknak a mérete általában eltérő.
#include <stdio.h> int main () { printf ( "%s \n " , ( sizeof ( 'a' ) == sizeof ( char )) ? "C++" : "C" ); return 0 ; }Ahogy Stroustrup megjegyzi: "Minél jobban ismeri a C-t, annál nehezebb lesz elkerülnie a C++ C-stílusú programozást, miközben elveszíti a C++ lehetséges előnyeit." Ebből a célból a következő ajánlásokat fogalmazza meg a C programozóknak, hogy teljes mértékben kihasználhassák a C++ előnyeit:
A jelenlegi ISO/IEC 14882:2017 nyelvi szabvány 2017 decemberében jelent meg . Nem hivatalosan C++17 -nek nevezik . A szabvány következő, 2020-ra tervezett változatának nem hivatalos megnevezése C++20 .
A nyelv szerzője, Björn Stroustrup [19] [20] [21] szerint a nyelv további fejlődéséről és kilátásairól szólva a következőket különböztetjük meg:
Ez egy példaprogram Hello, world! , amely a szabványos könyvtár használatával üzenetet nyomtat a konzolra , és kilép.
#include <iostream> névtér használata std ; int main () { cout << "Helló, világ!" << endl ; return 0 ; }A modern C++ lehetővé teszi az összetettebb problémák egyszerű megoldását. Ez a példa többek között a Standard Template Library ( STL ) tárolók használatát mutatja be.
#include <iostream> // az std::cout használatához #include <vektor> // dinamikus tömböt tartalmaz #include <térkép> // szótári adattípust tartalmaz #include <karakterlánc> int main () { // Importálja az "std" névtérben lévő összes deklarációt a globális névtérbe. névtér használata std ; // Karakterlánc-kulcsokkal és adatokkal rendelkező asszociatív tárolót karakterláncvektorként deklarálunk. térkép < string , vektor < string > > elemek ; // Adjon hozzá néhány embert ehhez az asszociációs tárolóhoz, és adjon nekik néhány elemet. tételek [ "Anya" ]. push_back ( "sál" ); tételek [ "Dmitrij" ]. push_back ( "jegyek" ); tételek [ "Anya" ]. push_back ( "kölyökkutya" ); // Végigpörgetés az összes objektumon a tárolóban for ( const auto & person : items ) { // személy két objektum párja: a person.first a neve, // a személy.második az elemeinek listája (karakterláncok vektora) cout << person . első << " hord " << személyt . második . méret () << "elemek" << endl ; } }Ez a példa az összes nevet az std névtérből importálja az egyszerűség kedvéért. Valós programban ez nem ajánlott, mivel névütközéssel találkozhatunk. A nyelv lehetővé teszi egyedi objektumok importálását:
#include <vektor> int main () { std :: vektor használatával ; vektor < int > saját_vektor ; }C++-ban (mint a C-ben), ha a program végrehajtása eléri a függvény végét main(), akkor ez egyenértékű a -val return 0;. Ez a függvényen kívül más függvényre nem igaz main().
Több olyan tanulmány is ismert, amelyben több programozási nyelv többé-kevésbé objektív összehasonlítására is kísérletet tettek, ezek közül az egyik a C ++. Különösen:
Az Ada nyelv funkciókészletét és alkalmazási területeit tekintve közel áll a C++-hoz: egy Simula-szerű objektumorientált kiegészítéssel (ugyanaz az „Algol osztályokkal” modellel, mint a C++-ban), statikus gépeléssel, lefordított szerkezeti nyelv. , általános programozási eszközök, nagy és összetett szoftverrendszerek fejlesztésére. Ugyanakkor az ideológiában alapvetően különbözik: a C ++-tól eltérően az Ada komplex szoftvergyártók korábban gondosan kidolgozott feltételeire épült, fokozott megbízhatósági követelményekkel, ami nyomot hagyott a szoftver szintaxisában és szemantikájában. nyelv.
Kevés közvetlen összehasonlítás létezik az Ada és a C++ kódolás hatékonyságáról. A fent említett cikkben [22] a modellprobléma Adában való megoldása körülbelül 30%-kal kisebb méretű (soros) kódot eredményezett, mint a C++-ban. Maguk a nyelvek tulajdonságainak összehasonlítását számos forrás megadja, például Jim Rogers cikke az AdaHome-ról [28] több mint 50 pontot sorol fel e nyelvek tulajdonságai között, amelyek többsége az Ada javára szól. (több funkció, rugalmasabb viselkedés, kisebb a hibalehetőség). Bár az adai támogatók kijelentései közül sok ellentmondásos, és némelyik egyértelműen elavult, általánosságban levonható a következtetés:
Stephen Zeiger, a Rational Software Corporation munkatársa [29] cikkében azt állítják, hogy az Adában a fejlesztés általában 60%-kal olcsóbb, és 9-szer kevesebb hibával rendelkező kódot eredményez, mint a C-ben. Bár ezek az eredmények nem vihetők át közvetlenül a C++-ba, mégis érdekesek, mivel a C++ számos hiányossága a C-ből öröklődik.
A Java nem tekinthető a C++ teljes helyettesítésének, biztonságos nyelvnek készült, alacsony belépési küszöb mellett nagy hordozhatóságú egyedi alkalmazások fejlesztéséhez [30] , és alapvetően alkalmatlan bizonyos C++-ban fejlesztett alkalmazásokhoz. A Java azonban hatókörén belül nagyon is igazi versenytársa a C++-nak. A Java előnyeit általában a következőképpen említik:
Ugyanakkor a szemétgyűjtő és a virtuális gép használata nehezen áthidalható korlátokat teremt. A Java programok általában lassabbak, lényegesen több memóriát igényelnek, és a virtuális gép elszigeteli a programot az operációs rendszertől, ami lehetetlenné teszi az alacsony szintű programozást.
Egy empirikus tanulmány [24] nem talált szignifikáns különbséget a C++ és a Java fejlesztési sebességében. A tanulmány [26] azt is kimutatta, hogy nem mindig helytálló az az elképzelés, hogy ezeken a nyelveken jelentős különbségek vannak a programok sebességében: három tesztből kettőben a Java és C++ alkalmazások sebessége bizonyult hasonló. Ugyanakkor a Java tömörebb - a kód mennyiségének különbsége körülbelül 10-15% volt.
Az eredeti C folyamatosan fejlődik, számos nagyszabású projektet fejlesztenek benne: ez az operációs rendszerek fejlesztésének fő nyelve, számos dinamikus játék játékmotorja és számos alkalmazási alkalmazás íródik bele. Számos szakértő úgy érvel, hogy a C helyettesítése C++-ra nem növeli a fejlesztés hatékonyságát, hanem a projekt szükségtelen bonyolításához, a megbízhatóság csökkenéséhez és a karbantartási költségek növekedéséhez vezet. Különösen:
Nincs meggyőző bizonyíték arra, hogy a C++ jobb lenne a C-nél sem a programozói termelékenység, sem a programtulajdonságok tekintetében. Bár vannak olyan tanulmányok [32] , amelyek szerint a C programozók a teljes fejlesztési idő körülbelül 30-40%-át (a hibakeresést leszámítva) a memóriakezelésre fordítják, a fejlesztők általános termelékenységét összehasonlítva [22] a C és a C++ közel áll egymáshoz.
Az alacsony szintű programozásban a C++ új funkcióinak nagy része nem alkalmazható a megnövekedett többletterhelés miatt: a virtuális funkciók dinamikus valós cím számítást (RVA) igényelnek, a sablonok kódfelfújáshoz és rossz optimalizálási képességekhez vezetnek, a futásidejű könyvtár (RTL) nagyon nagy, és ennek elutasítása megfosztja a C ++ legtöbb funkcióját (már csak a new/ műveletek elérhetetlensége miatt is delete). Ennek eredményeként a programozónak a C-től örökölt funkciókra kell korlátoznia magát, ami értelmetlenné teszi a C ++ használatát:
… az egyetlen módja annak, hogy jó, hatékony, alacsony szintű, hordozható C++-t kapjunk, ha korlátozzuk magunkat mindazokra a dolgokra, amelyek triviálisan elérhetők C-ben. És ha a projektet C-re korlátozzuk, az azt jelenti, hogy az emberek nem fogják kidobni, és sok olyan programozó lesz elérhető, akik valóban jól értik az alacsony szintű funkciókat, és nem hagyják el őket az idióta "objektummodell" miatt. ostobaság.
… amikor a hatékonyság a legfontosabb, a C++ "előnyei" óriási hiba lesz.
Egy kísérletben [22] a szkript- és funkcionális nyelvek, különösen a Haskell 2-3-szoros növekedést mutattak a programozási idő és a kódméret tekintetében a C++ programokhoz képest. Másrészt a C++ programok ugyanilyen gyorsabbnak bizonyultak. A szerzők elismerik, hogy adataik nem képeznek reprezentatív mintát, és tartózkodnak a kategorikus következtetések levonásától.
Egy másik kísérletben [34] a szigorú funkcionális nyelvek ( Standard ML , OCaml ) 10-szeres általános fejlődési gyorsulást mutattak (főleg a hibák korai felismerése miatt), megközelítőleg azonos teljesítménymutatókkal (sok fordító több módban is használt).
Lutz Prehelt [24] tanulmányában , mintegy 80 önkéntesek által írt megoldás feldolgozásának eredményei alapján, különösen a következő következtetésekre jutottak:
A kritikusok leggyakrabban nem ellenzik a C++-t egyetlen másik nyelvvel sem, hanem azzal érvelnek, hogy egyetlen nyelv használatának elutasítása, amelynek számos hibája van, a projekt olyan részfeladatokra bontása javára, amelyek különböző nyelveken megoldhatók, amelyek a legalkalmasabbak jelentősen kevésbé időigényessé teszik a fejlesztést, miközben javítják a programozás minőségi mutatóit [35] [36] . Ugyanezen okból kifogásolják a C-vel való kompatibilitás fenntartását: ha a feladat egy része alacsony szintű funkciókat igényel, akkor ésszerűbb ezt a részt külön alrendszerre választani és C-be írni.
A C ++ támogatói viszont azt állítják, hogy a nyelvközi interakció technikai és szervezési problémáinak kiküszöbölése több speciális nyelv helyett egy univerzális nyelv használatával fontosabb, mint az univerzális nyelv tökéletlenségéből eredő veszteségek, azaz a C ++ szolgáltatáskészlet széles skálája mentség az egyes funkciók hiányosságaira; beleértve a C-ből örökölt hátrányokat is a kompatibilitás előnyei indokolják (lásd fent ).
Így a C ++ ugyanazokat a tulajdonságait - hangerő, összetettség, eklektika és az alkalmazási célterület hiánya - a támogatók " fő előnynek ", a kritikusok pedig " a fő hátránynak " tekintik.
A nyelv ideológiája összekeveri a „ viselkedés -szabályozást ” a „ hatékonyság -szabályozással ”: a „ nem fizet azért, amit nem használ ” elv azt sugallja, hogy a programozó számára a programvégrehajtás minden aspektusa feletti teljes ellenőrzést egy meglehetősen alacsony szint szükséges és elégséges feltétel a magas kódhatékonyság eléréséhez. Valójában ez egyetlen nagy programra sem igaz: az alacsony szintű optimalizálás rákényszerítése a programozóra, amit egy jó minőségű tartományspecifikus nyelvi fordító nyilvánvalóan hatékonyabban tud végrehajtani, csak a kód mennyiségének növekedéséhez vezet, a programozási munkaintenzitás növekedése, valamint a kód érthetőségének és tesztelhetőségének csökkenése. Így a „nem fizess azért, amit nem használnak” elve nem igazán biztosítja a kívánt hatékonysági előnyöket, hanem negatívan befolyásolja a minőséget.
Komponens és objektum-orientált programozásAlan Kay szerint a C++-ban használt „ Algol osztályokkal” objektummodell a teljes terjedelem, a kód újrafelhasználása , az érthetőség, a módosíthatóság és a tesztelhetőség tekintetében gyengébb az Objective-C- ben használt „minden egy objektum” modellnél [37] . .
A C++ öröklődési modell összetett, nehezen megvalósítható, ugyanakkor összetett hierarchiák létrehozását váltja ki az osztályok közötti természetellenes kapcsolatokkal (például egymásba ágyazás helyett öröklődés). Az eredmény szorosan összekapcsolt osztályok létrehozása homályosan elkülönülő funkcionalitással. Például a [38] -ban van egy oktató és ajánló példa a "lista" osztály megvalósítására a "lista elem" osztály alosztályaként, amely viszont hozzáférési funkciókat tartalmaz más listaelemekhez. Ez a típuskapcsolat matematikailag abszurd, és szigorúbb nyelveken reprodukálhatatlan. Egyes könyvtárak ideológiája megkívánja az osztályhierarchiában felfelé és lefelé történő kézi típussorolást ( static_castés dynamic_cast), ami sérti a nyelv típusbiztonságát . A C++ oldatok magas viszkozitása miatt a projekt nagy részét újra kell fejleszteni minimális változtatásokkal a fejlesztési folyamat későbbi szakaszában. Az ilyen problémák szemléletes példája a [35] dokumentumban található.
Ahogy Ian Joyner [39] rámutat , a C++ tévesen egyenlővé teszi a beágyazást (vagyis az adatok objektumokba helyezését és a megvalósítás elválasztását az interfésztől) és az implementáció elrejtését. Ez megnehezíti az osztályadatokhoz való hozzáférést, és megköveteli, hogy interfészét szinte kizárólag hozzáférési függvényeken keresztül valósítsák meg (ami viszont növeli a kód mennyiségét és bonyolítja azt).
A típusegyeztetés a C++ nyelven az azonosítók szintjén van meghatározva, nem az aláírások szintjén. Ez lehetetlenné teszi az interfész illesztésen alapuló komponensek cseréjét, ezért a könyvtári szinten megvalósított új funkcionalitások rendszerbe foglalása a meglévő kód manuális módosítását igényli [40] . Ahogy Linus Torvalds [33] rámutat , a C++ nyelvben "a kód csak addig tűnik elvontnak, amíg nem kell megváltoztatni."
A C++ kritikáját az OOP szempontjából a [39] tartalmazza .
MetaprogramozásA C++ generatív metaprogramozása sablon- és előfeldolgozó alapú , munkaigényes és korlátozott hatókörű. A C++ sablonrendszer valójában a primitív funkcionális programozási nyelv fordítási idejű változata. Ennek a nyelvnek szinte nincs átfedése magával a C ++-szal, ezért az absztrakciók összetettségének növekedési lehetősége korlátozott. A C++ sablonokat használó programok érthetősége és tesztelhetősége rendkívül rossz, a sablonok kibontása pedig maga is nem hatékony kódot generál, mivel a sablonnyelv nem ad lehetőséget az optimalizálásra (lásd még #Számítási hatékonyság fejezet ). Az így megvalósított beágyazott tartományspecifikus nyelvek továbbra is megkövetelik magának a C++-nak a ismeretét, ami nem ad teljes értékű munkamegosztást. Így a C++ képessége magának a C++-nak a képességeinek kiterjesztésére meglehetősen korlátozott [41] [42] .
Cross-platformA hordozható C++ kód megírása nagy jártasságot és tapasztalatot igényel, és a "hanyag" C++ kód nagy valószínűséggel nem hordozható [43] . Linus Torvalds szerint a C-hez hasonló C++ hordozhatóság eléréséhez a programozónak a C-ből örökölt C++ jellemzőkre kell korlátoznia magát [33] . A szabvány számos „implementation-defined”-ként definiált elemet tartalmaz (például az osztálymetódusokra mutató pointerek mérete a különböző fordítóprogramokban 4-20 bájt között változik [44] ), ami rontja az ezeket használó programok hordozhatóságát.
A nyelvi szabványosítás direktíva , a hiányos visszafelé kompatibilitás és a szabvány különböző verzióinak követelményeinek inkonzisztenciája problémákhoz vezet a programok különböző fordítók, sőt ugyanazon fordítók verziói közötti áthelyezésében.
A nyelv olyan eszközöket tartalmaz, amelyek lehetővé teszik a programozó számára, hogy megsértse az adott esetben adott programozási fegyelmet. Például egy módosító constbeállítja egy objektum állapotváltoztathatatlanságának tulajdonságát, de a módosító kifejezetten arra lettmutable tervezve , hogy engedélyt kényszerítsen a const objektumon belüli állapot megváltoztatására, vagyis az állandósági kényszer megsértésére. Ezenkívül megengedett egy attribútum dinamikus eltávolítása egy állandó objektumból, L-értékké alakítva azt. Az ilyen tulajdonságok jelenléte a nyelvben értelmetlenné teszi a kód formális ellenőrzésére tett kísérleteket , és lehetetlen a korlátozások használata az optimalizáláshoz. const
Ellenőrizetlen makróhelyettesítésA C makró helyettesítési lehetőségek ( #define) éppoly erősek, mint veszélyesek. A C++-ban megmaradnak annak ellenére, hogy minden olyan feladathoz, amelyre C-ben biztosították, a C++ szigorúbb és speciálisabb lehetőségeket biztosított - sablonok, funkció túlterhelés, soron belüli függvények, névterek, fejlettebb gépelés, alkalmazás kiterjesztése a const módosító. , stb. Sok potenciálisan veszélyes makró található a C-ből örökölt standard könyvtárakban [45] . A sablon metaprogramozást néha a makróhelyettesítés használatával is kombinálják, hogy ún. " szintaktikus cukor ".
Túlterhelési problémákA funkció és az operátor túlterhelésének C++ elvei jelentős kódduplikációhoz vezetnek. Eredetileg az úgynevezett " szintaktikai cukor " bevezetésére szánták, az operátortúlterhelés a C++ nyelvben ösztönzi az elemi operátorok ellenőrizetlen viselkedését a különböző típusoknál. Ez drámaian növeli a hibák kockázatát, különösen azért, mert lehetetlen új szintaxist bevezetni és a meglévőt megváltoztatni (például új operátorokat létrehozni, prioritásokat vagy asszociativitást módosítani), bár a szabványos C ++ operátorok szintaxisa megfelelő a korántsem minden típusú szemantika, amelyet esetleg be kell vezetni a programba. Bizonyos problémákat okoz az operátorok könnyű túlterhelésének lehetősége , ami rendkívül alattomos és nehezen fellelhető hibákat generálhat. Ugyanakkor néhány intuitívan elvárt művelet (dinamikus objektumok tisztítása kivételek dobása esetén) nem kerül végrehajtásra a C++-ban, és a túlterhelt függvények és operátorok jelentős része implicit módon meghívásra kerül (típusöntés, osztályok ideiglenes példányainak létrehozása stb. .). Ennek eredményeként az eredetileg a programok világosabbá tételére, valamint a fejlesztés és karbantarthatóság javítására szolgáló eszközök a szükségtelenül bonyolult és megbízhatatlan kódok újabb forrásaivá válnak. newdelete
A C++ sablonok használata paraméteres polimorfizmus a forráskód szintjén, de lefordítva ad hoc polimorfizmusba (azaz függvénytúlterhelésbe) alakul, ami a gépi kód mennyiségének jelentős növekedéséhez vezet azokhoz a nyelvekhez képest, amelyek rendelkeznek igazi polimorf típusú rendszer (az ML leszármazottai ). A gépi kód méretének csökkentése érdekében megpróbálják automatikusan feldolgozni a forráskódot a sablonok letekercselési szakasza előtt [46] [47] . Egy másik megoldás lehet a sablonok exportálása, amelyet még 1998-ban szabványosítottak, de nem minden fordítónál érhető el, mivel nehezen kivitelezhető [48] [49] [vélemények 4] és C ++ sablonkönyvtárak importálása. jelentősen eltérő C++ szemantikával rendelkező nyelvekbe még mindig haszontalan lenne. A C++ támogatói vitatják a kódfelfúvódás mértékét, mint eltúlzott [50] , még azt a tényt is figyelmen kívül hagyva, hogy a C-ben a parametrikus polimorfizmus közvetlenül, azaz a függvénytestek megkettőzése nélkül történik. Ugyanakkor a C++ támogatói úgy vélik, hogy a C paraméteres polimorfizmusa veszélyes – vagyis veszélyesebb, mint a C-ből C++-ba való átmenet (a C++ ellenzői ennek az ellenkezőjével érvelnek – lásd fent).
Optimalizálási lehetőségA gyenge típusú rendszer és a rengeteg mellékhatás miatt rendkívül nehézkessé válik a programok egyenértékű konvertálása, ezért számos optimalizáló algoritmus beágyazása a fordítóba, mint például a programok automatikus párhuzamosítása , a gyakori részkifejezések eltávolítása , λ-emelés, hívások eljárások folytatásos passzírozással , szuperfordítással stb. Ennek eredményeként a C++ programok tényleges hatékonyságát korlátozza a programozók készségei és az adott projektbe fektetett erőfeszítések, és a „hanyag” megvalósítás hatékonysága jelentősen gyengébb lehet, mint a „hanyag” ” implementációk magasabb szintű nyelveken, amit a nyelvek összehasonlító tesztjei is megerősítenek [34] . Ez jelentős akadályt jelent a C++ adatbányászati iparban való használata előtt .
Hatékony memóriakezelésA hatékony memóriakezelés felelőssége a fejlesztő vállára esik, és a fejlesztő képességeitől függ. Az automatikus memóriakezeléshez C ++-ban az ún. "intelligens mutatók", a kézi memóriakezelés csökkenti maguknak a programozóknak a hatékonyságát (lásd a Hatékonyság című részt ) . A szemétgyűjtés számos implementációja , mint például a régiók statikus következtetése , nem alkalmazható C++ programokra (pontosabban ehhez egy új nyelvi tolmács implementálása szükséges a C++ nyelven felül, ami a legtöbb objektív tulajdonságában nagyon különbözik a C++-tól és az általános ideológiában) az AST -hez való közvetlen hozzáférés szükségessége miatt .
A teljesítménytényezők korrelációja a fejlesztési költségekkel, valamint a programozói közösségben művelt általános fegyelem és programozási kultúra fontos azon ügyfelek számára, akik projektjeik megvalósításához nyelvet választanak (és ennek megfelelően ezt a fejlesztői nyelvet részesítik előnyben), valamint azoknak, akik elkezdenek programozást tanulni, különösen azzal a szándékkal, hogy saját igényeinek megfelelően programozzanak.
Programozási minőség és kultúraA C++ elve, hogy „ ne kényszerítsünk ki egy „jó programozási stílust ”, ellentétes a programozás ipari megközelítésével, melyben a szoftver minősége és a kód karbantartásának lehetősége játssza a vezető szerepet, nem csak a szerző. , és melyek azok a nyelvek, amelyek minimálisra csökkentik az emberi tényező hatását , vagyis csak „ jó” programozási stílust kényszerítenek ki , bár ezeknek a nyelveknek magasabb lehet a belépési küszöbük.
Egyes vélemények szerint a C++ használatának előnyben részesítése (alternatív nyelvválasztás lehetőségével) negatívan jellemzi a programozó szakmai tulajdonságait. Linus Torvalds azt mondja, hogy a jelöltek pozitív véleményét a C++-ról lemorzsolódási kritériumként használja [vélemények 3] :
A C++ egy borzasztó nyelv. Ami még borzasztóbbá teszi, az az a tény, hogy sok írástudatlan programozó használja... Őszintén szólva, még ha nincs is más ok a C kiválasztására, mint a C++ programozók távoltartása, ez önmagában is jó ok lenne a használatára. C.
…Arra a következtetésre jutottam, hogy szívesebben rúgnék ki mindenkit, aki szívesebben dolgozna C++-ban, mint C-ben, hogy ne tegye tönkre azt a projektet, amelyben részt veszek.
A nyelv folyamatos fejlődése arra ösztönzi (és néha kényszeríti is) a programozókat, hogy újra és újra módosítsák a már hibakeresett kódot – ez nemcsak a fejlesztés költségeit növeli, hanem azzal a kockázattal is jár, hogy a hibakereső kódban új hibákat visznek be. Különösen, bár a visszafelé kompatibilitás a C-vel eredetileg a C++ egyik alapelve volt, 1999 óta a C megszűnt a C++ részhalmaza lenni, így a hibakereső C-kód már nem használható egy C++-projektben módosítás nélkül.
Bonyolultság önmagáértA C++-t apologétái éppen azért határozzák meg "a legerősebbnek" , mert tele van veszélyes, egymásnak ellentmondó tulajdonságokkal. Eric Raymond szerint ez magát a nyelvet teszi a programozók személyes önmegerősítésének talajává, és a fejlesztési folyamatot öncélúvá változtatja:
A programozók gyakran rikító egyéniségek, akik büszkék arra, hogy képesek kezelni a bonyolultságokat és az absztrakciókat ügyesen. Gyakran versenyeznek egymással, és megpróbálják kitalálni, hogy ki tudja létrehozni a "legbonyolultabb és legszebb összetettséget". ... a riválisok úgy vélik, hogy fel kell venniük a versenyt mások „dekorációival”, sajátjuk hozzáadásával. Nemsokára a "masszív daganat" válik az iparág szabványává, és mindenki olyan nagy, bugos programokat futtat, amelyeket még az alkotóik sem tudnak kielégíteni.
…
… ez a megközelítés bajba kerülhet, ha a programozók egyszerű dolgokat bonyolult módon csinálnak, egyszerűen azért, mert ismerik ezeket a módszereket és tudják, hogyan kell használni őket.
Megfigyeltek olyan eseteket, amikor a gondatlan programozók a C ++ erős kontextusfüggőségét és a makródefiníciók fordító általi nyomon követésének hiányát kihasználva lelassították a projekt fejlődését azzal, hogy egy-két pluszt írtak, fordítói szempontból helyesen. nézetből, kódsorokból, de bevezetnek egy nehezen észlelhető, spontán módon megnyilvánuló hibát az ő kárukra. Például:
#define if(a) if(rand())A bizonyítottan helyes nyelveken még fejlett makrólehetőségekkel sem lehet ilyen módon kárt okozni.
Megbízhatatlan termékA mellékhatások ésszerűtlen sokasága, a nyelv futásidejű rendszerének ellenőrzésének hiányával és a gyenge típusú rendszerrel kombinálva a C++ programokat hajlamossá teszi előre nem látható végzetes összeomlásokra (a jól ismert összeomlások olyan üzenetekkel, mint "Hozzáférés megsértése", "Tiszta virtuális funkció hívás" vagy "A program illegális műveletet hajtott végre, és be lesz zárva"), amely kizárja a C ++ használatát, magas hibatűrési követelményekkel. Ezenkívül megnöveli magának a fejlesztési folyamatnak az időtartamát [34] .
ProjektmenedzsmentA fent felsorolt tényezők a C++ projektmenedzsment komplexitását a szoftverfejlesztési ipar egyik legmagasabb fokává teszik.
James Coggins, a The C++ Report
négyéves rovatvezetője kifejti:
A probléma az, hogy az OOP programozói vérfertőző alkalmazásokkal kísérleteztek, és az absztrakció alacsony szintjére törekedtek. Például olyan osztályokat építettek, mint a „linked list” a „felhasználói felület” vagy a „sugárzási nyaláb” vagy „végeselem-modell” helyett. Sajnos az erős típusellenőrzés, amely segít a C++ programozóknak elkerülni a hibákat, megnehezíti a nagy objektumok kicsikből való építését is.
A C++ egyetlen közvetlen leszármazottja a D nyelv , amely a C++ átdolgozása a legnyilvánvalóbb problémáinak megoldására. A szerzők lemondtak a C-vel való kompatibilitásról, megtartották a C ++ szintaxisát és számos alapelvét, és olyan funkciókat vezettek be a nyelvbe, amelyek az új nyelvekre jellemzőek. A D-nek nincs előfeldolgozója, nincs fejlécfájlja, nincs többszörös öröklődése, de modulrendszere, interfészek, asszociatív tömbök, unicode támogatása karakterláncokban, szemétgyűjtés (a kézi memóriakezelés lehetőségének fenntartása mellett), beépített többszálú, típuskövetkeztetés , tiszta függvények és megváltoztathatatlan értékek explicit deklarációja. A D használata nagyon korlátozott, nem tekinthető a C ++ valódi versenytársának.
A C++ legrégebbi vetélytársa az alacsony szintű feladatokban az Objective-C , amely szintén a C objektummodellel való kombinálásának elvén épült , csak az objektummodellt örökli a Smalltalk . Az Objective-C-t, akárcsak leszármazottját a Swiftet , széles körben használják szoftverfejlesztésre MacOS és iOS rendszeren.
A C++ egyik első alternatívája az alkalmazásprogramozásban a Java nyelv volt . Gyakran tévesen a C++ közvetlen leszármazottjának tekintik; Valójában a Java szemantikája a Modula-2 nyelvből öröklődik , és a C++ alapvető szemantikája nem követhető nyomon a Java-ban. Tekintettel erre, és a nyelvek genealógiájára (a Modula-2 a Simula leszármazottja , akárcsak a C++, de nem C), a Java-t helyesebben a C++ " másodunokatestvérének " nevezik, nem pedig " örökösének ". Ugyanez mondható el a C# nyelvről is, bár a C++-hoz való affinitás százaléka valamivel magasabb, mint a Javaé.
A Java és a C# biztonságát és fejlesztési sebességét a C++ képességeivel kombinálni próbálták a Managed C++ dialektus (később C++/CLI ). A Microsoft elsősorban a meglévő C++ projektek Microsoft .NET platformra történő portolására fejlesztette ki. A CLR alatt futó programok a .NET-könyvtárak teljes tömbjét használhatják, de a C++-szolgáltatások használatára számos korlátozás vonatkozik, ami hatékonyan csökkenti a C++-t C#-ra. Ez a nyelvjárás nem kapott széles körű elismerést, és főként a tiszta C ++ nyelven írt könyvtárak összekapcsolására szolgál C # alkalmazásokkal.
A C nyelv fejlesztésének egy másik módja, ha nem objektum-orientált programozással, hanem aplikatív programozással kombináljuk , vagyis az alacsony szintű programok absztrakcióját, szigorát és modularitását javítjuk a kiszámítható viselkedés és a hivatkozási átlátszóság biztosításával . Az ilyen jellegű munkákra példák a BitC , a Cyclone és a Limbo nyelvek . Bár vannak sikeres kísérletek az FP használatára valós idejű problémákban C eszközökkel való integráció nélkül [52] [53] [54] , jelenleg (2013) az alacsony szintű fejlesztésben a C eszközök használata bizonyos mértékig. jobb arányban áll a munkaintenzitás és a hatékonyság között. A Python és a Lua fejlesztői sok erőfeszítést tettek a Python és a Lua fejlesztésére annak biztosítására, hogy ezeket a nyelveket használják a C++ programozók, így az FP-hez szorosan kapcsolódó nyelvek közül ezek a nyelvek a leggyakrabban megjegyezték, hogy a C++-szal együtt kell használni ugyanabban a projektben. A C++ és az FP közötti legjelentősebb érintkezési pontok a C++-ban kifejlesztett wxWidgets és Qt könyvtárak C++-specifikus ideológiájú kötései Lisp -hez , Haskell -hez és Python -hoz (a legtöbb esetben a funkcionális nyelvekhez való kötések a nyelven írt könyvtárakhoz készülnek C vagy más funkcionális nyelvek).
Egy másik nyelv, amelyet a C++ versenytársának tartanak, a Nemerle , amely a Hindley-Milner tipizálási modell és a Common Lisp makró részhalmazának a C#-val való kombinálására tett kísérlet eredménye [55] . Ugyanebben a szellemben a Microsoft F# -ja, az ML nyelvjárása .NET környezetre adaptálva.
A C/C++ ipari helyettesítésére tett kísérlet a Go programozási nyelv volt, amelyet a Google fejlesztett ki 2009-ben . A nyelv szerzői egyenesen rámutatnak arra, hogy létrehozásának indítéka a fejlesztési folyamat hiányosságai, amelyeket a C és C ++ nyelvek sajátosságai okoztak [56] . A Go egy kompakt, egyszerű imperatív nyelv C-szerű szintaxissal, előprocesszor nélkül, statikus gépeléssel, erős gépeléssel, csomagoló rendszerrel, automatikus memóriakezeléssel, néhány funkcionális funkcióval, gazdaságosan felépített OOP alrendszerrel, implementáció öröklődés támogatása nélkül, de interfésszel és kacsa gépeléssel , beépített többszálú korutin és csövek alapján (a-la Occam ). A nyelvet a C ++ alternatívájaként pozicionálják, vagyis elsősorban rendkívül összetett, rendkívül összetett számítástechnikai rendszerek csoportos fejlesztésének eszközeként, beleértve az elosztottakat is, szükség esetén lehetővé téve az alacsony szintű programozást.
Ugyanabban az ökológiai résben a C / C ++-szal a Rust, amelyet 2010-ben fejlesztettek ki és a Mozilla Corporation karbantartott , és a szemétgyűjtő használata nélküli biztonságos memóriakezelésre összpontosít . A Microsoft 2019-ben különösen azt a tervet jelentette be, hogy a C / C ++ részben Rust-ra cseréli [57] .
Szótárak és enciklopédiák | ||||
---|---|---|---|---|
|
Programozási nyelvek | |
---|---|
|
ISO szabványok | |
---|---|
| |
1 -től 9999 -ig |
|
10 000 és 19999 között |
|
20000+ | |
Lásd még: Azon cikkek listája, amelyek címe "ISO"-val kezdődik |
C++ | |
---|---|
Sajátosságok | |
Néhány könyvtár | |
Fordítók | |
befolyásolta | |
|