wd wp Пошук:

C++

C++ (Сі++) — кампіляваная статычна тыпізаваная мова праграмавання агульнага прызначэння. Падтрымлівае розныя парадыгмы праграмавання, але, у параўнанні са сваёй папярэдніцай мовай Сі, найбольшая ўвага скіравана на падтрымку аб’ектна-арыентаванага і абагульненага праграмавання.[1]

Назва «C++» паходзіць ад назвы мовы Сі (C), у якой унарны (аднамесны) аператар ++ пазначае прырост зменнай на адзінку.

У 1990-х гадах мова стала адной з самых ўжывальных моў праграмавання агульнага прызначэння.

Пры стварэнні C++ імкнуліся захаваць сумяшчальнасць з мовай Сі. Большасць праграм на Сі можна, амаль не змяняючы, сабраць і з дапамогай кампілятара C++. Мова C++ мае сінтаксіс, заснаваны на сінтаксісе Сі.

Гісторыя

Мова з’явілася напачатку 1980-х гадоў, калі супрацоўнік фірмы Bell Laboratories Б’ёрн Страўструп прыдумаў шэраг удасканаленняў да мовы Сі пад уласныя патрэбы. Да пачатку афіцыйнай стандартызацыі мова развівалася галоўным чынам сіламі Страўструпа ў адказ на запыты праграмісцкай супольнасці. У 1998 годзе быў прынят міжнародны стандарт мовы C++: ISO/IEC 14882:1998 «Standard for the C++ Programming Language»; пасля прыняцця тэхнічных выпраўленняў да стандарту ў 2003 годзе — цяперашняя версія гэтага стандарту — ISO/IEC 14882:2003.

Раннія версіі мовы, вядомыя пад назвай «C з класамі», пачалі з’яўляцца ў 1980-я гады.[2] Ідэя стварэння новай мовы бярэ пачатак з доследаў Страўструпа ў праграмаванні падчас працы над дысертацыяй. Ён выявіў, што мова мадэлявання Сімула (Simula) мае такія магчымасці, якія былі б вельмі карыснымі пры распрацоўцы вялікага праграмнага забеспячэння, але працуе занадта павольна. У той жа час мова BCPL даволі хуткая, але занадта блізкая да моў нізкага ўзроўню і не падыходзіць для распрацоўкі вялікага праграмнага забеспячэння. Страўструп пачаў працаваць у Bell Labs над задачамі тэорыі чэрг (у прыкладаннях да мадэлявання тэлефонных выклікаў). Спробы прымяніць існаваўшыя ў той час мовы мадэлявання засталіся безвыніковымі. Успомніўшы доследы са сваёй дысертацыі, Страўструп вырашыў дапоўніць мову Сі (пераемніцу BCPL) магчымасцямі мовы Сімула. Мова Сі, якая была асноўнай мовай сістэмы UNIX, на якой працавалі камп’ютары Bell, хуткая, шматфункцыянальная і пераносная. Страўструп дадаў да яе магчымасць працы з класамі і аб’ектамі. У выніку, практычныя задачы мадэлявання сталі даступнымі для развязання як з пункту гледжання часу распрацоўкі (дзякуючы выкарыстанню Сімула-падобных класаў) так і з пункту гледжання часу вылічэнняў (дзякуючы хуткадзеянню Сі). Напачатку ў Сі былі ўключаны класы (з інкапсуляцыяй), вытворныя класы, строгая праверка тыпаў, inline-функцыі і аргументы па змаўчанні.

Распрацоўваючы Сі з класамі (пазней C++), Страўструп таксама напісаў праграму cfront — транслятар, які перакладаў зыходны код Сі з класамі у зыходны код звычайнай Сі. Новая мова, нечакана для аўтара, набыла вялікую папулярнасць сярод калег, і неўзабаве Страўструп ужо не мог падтрымліваць яе асабіста, адказваючы на тысячы пытанняў.

У 1983 годзе адбылося перайменаванне мовы з Сі з класамі у C++. Акрамя таго, у яе былі ўключаны новыя магчымасці, такія як віртуальныя функцыі, перагрузка функцый і аператараў, спасылкі, канстанты (сталыя), карыстальніцкі кантроль над кіраваннем свабоднай памяццю, палепшаная праверка тыпаў і новы стыль каментарыяў (//). Яе першы камерцыйны выпуск адбыўся ў кастрычніку 1985 года.

Развіццё і ўпарадкаванне мовы

У 1985 годзе выйшла першае выданне кнігі «Мова праграмавання C++», першае апісанне гэтай мовы, што было надзвычай важным з-за адсутнасці афіцыйнага стандарту. У 1989 годзе адбыўся выхад C++ версіі 2.0. Яго новыя магчымасці ўключалі множнае наследаванне, абстрактныя класы, статычныя функцыі-члены, функцыі-канстанты і ахаваныя члены.

У 1990 годзе выйшла «Каментаванае даведачнае кіраўніцтва па C++», якое пасля легла ў аснову стандарту. Апошнія абнаўленні ўключалі шаблоны, выключэнні, прасторы імён, новыя спосабы прывядзення тыпаў і булеўскі тып.

Стандартная бібліятэка мовы C++ таксама развівалася разам з ёю. Першым дабаўленнем к стандартнай бібліятэцы C++ сталі патокі ўводу/вываду, якія даюць сродкі для замены традыцыйных функцый Сі printf і scanf. Пазней самым значным крокам у развіцці стандартнай бібліятэкі стала ўключэнне ў яе Стандартнай бібліятэкі шаблонаў.

У 1998 годзе, пасля некалькіх гадоў працы, сумесны камітэт ANSI-ISO прыняў стандарт мовы C++ (ISO/IEC 14882:1998 — Мова праграмавання C++). На працягу некалькіх гадоў пасля афіцыйнага выхаду стандарту камітэт апрацоўваў паведамленні пра памылкі і ў выніку выпусціў выпраўленую версію стандарту C++ у 2003 годзе. У наш час працоўная група МОС (ISO) працуе над новай версіяй стандарту пад кодавай назвай C++09 (раней вядомы як C++0X), які павінен выйсці ў 2009 годзе.

Ніхто не валодае правамі на мову C++, гэта свабодная мова праграмавання. Аднак сам дакумент стандарту мовы (за выключэннем чарнавікоў) бясплатна не даступны.

Гісторыя назвы

Назва «C++» была прыдумана Рыкам Масіцці (Rick Mascitti) і ўпершыню была выкарыстана ў снежні 1983 года. Раней, на ступені распрацоўкі, новая мова называлася «Сі з класамі».[2]

Імя, атрыманае ў выніку, паходзіць ад аператара мовы Сі «++» (павелічэнне значэння зменнай на адзінку). Імя «C+» не было выкарыстана таму, што з’яўляецца сінтаксічнай памылкай у Сі і, акрамя таго, гэта імя было занята іншай мовай. Мова таксама не названа «D», бо «з’яўляецца пашырэннем Сі і не спрабуе здымаць праблемы шляхам выдалення элементаў Сі».[2]

Філасофія C++

У кнізе «Дызайн і эвалюцыя C++» Бьерн Страуструп апісвае прынцыпы, якіх ён прытрымліваўся пры распрацоўцы мовы C++.[3] Гэтыя прынцыпы тлумачаць, чаму C++ менавіта такая, якой яна ёсць. Некаторыя з іх:

Агляд мовы

Стандарт C++ на 1998 год складаецца з дзвюх асноўных частак: ядра мовы і стандартнай бібліятэкі.

Стандартная бібліятэка C++ увабрала ў сябе бібліятэку шаблонаў STL, якая распрацоўвалася адначасова са стандартам. Цяпер назва STL афіцыйна не ўжываецца, аднак у кругах праграмістаў на C++ і ў навучанні гэта назва выкарыстоўваецца для пазначэння часткі стандартнай бібліятэкі, якая змяшчае азначэнні шаблонаў кантэйнераў, ітэратараў, алгарытмаў і функтараў.

Стандарт C++ утрымоўвае нарматыўную спасылку на стандарт Сі ад 1990 года і не вызначае самастойна тыя функцыі стандартнай бібліятэкі, якія пазычаны са стандартнай бібліятэкі Сі.

Акрамя таго, існуе велізарная колькасць бібліятэк C++, якія не ўваходзяць у стандарт. У праграмах на C++ можна выкарыстоўваць шматлікія бібліятэкі Сі.

Мова праграмавання C++ вызначана стандартам, аднак за гэтай назвай могуць хавацца таксама няпоўныя, абмежаваныя, дастандартныя адмены мовы. Напачатку свайго існавання мова развівалася па-за фармальнымі рамкамі, адказваючы на задачы, якія ставіліся перад ёю. Развіццю мовы спадарожнічала развіццё крос-кампілятара cfront. Змены і новыя ўласціваці ў мове адлюстроўваліся ў змене нумара версіі крос-кампілятара. Гэтыя нумары версій крос-кампілятара распаўсюджваліся і на саму мову. Аднак цяпер звычайна пра версіі мовы C++ не кажуць.

Новыя магчымасці ў параўнанні з Сі

Новаўвядзеннямі C++ у параўнанні з Сі з’яўляюцца:

Мова C++ шмат у чым з’яўляецца надмноствам Сі. Новыя магчымасці C++ уключаюць аб’яўленні ў выглядзе выразаў, пераўтварэнні тыпаў у выглядзе функцый, аператары new і delete, тып bool, спасылкі, пашыранае паняцце нязменнасці аб’ектаў, падстаўляльныя (убудавальныя) функцыі, аргументы па змаўчанні, пераазначэнні, прасторы імён, класы (разам з усімі спалучанымі магчымасцямі, такімі як наследаванне, функцыі-члены, віртуальныя функцыі, абстрактныя класы і канструктары), пераазначэнні аператараў, шаблоны, аператар развязання прасторы імён ::, апрацоўку выключэнняў, дынамічнае атаясамленне і многае іншае. Таксама, мова C++ ў многіх выпадках стражэйшая за мову Сі ў дачыненні да праверкі тыпаў.

У C++ з’явіліся каментары ў выглядзе падвойнай касой рысы (//), якія былі ў папярэдніку мовы Сі — мове BCPL.

Некаторыя асаблівасці C++ пазней былі перанесены ў Сі, напрыклад ключавыя словы const і inline, аб’яўленні ў цыклах for і каментары ў стылі C++ (//). У пазнейшых рэалізацыях Сі таксама з’явіліся магчымасці, якіх няма ў C++, напрыклад макрасы vararg і палепшаная праца з масівамі-параметрамі.

Магчымасці, не звязаныя з ААП

У гэтым раздзеле апісваюцца магчымасці, непасрэдна не звязаныя з аб’ектна-арыентаваным праграмаваннем (ААП). Аднак, многія з іх набываюць асаблівую важнасць іменна ў спалучэнні з ААП.

Аператар delete правярае, што яе аргумент не NULL, у адваротным выпадку ён нічога не робіць. Пры стварэнні і выдаленні асобнікаў (аб’ектаў) класаў з дапамогай new і delete кампілятар устаўляе выклікі канструктара і дэструктара класа (гл. ніжэй).

void Print(int x);
void Print(double x);
void Print(int x, int y);
struct Date \{int day, month, year;\};
void operator ++(struct Date& date);

Аператары нічым не адрозніваюцца ад звычайных функцый (па сутнасці, аператар ёсць функцыяй, і ўсе адрозненні складаюцца ў тым, як выглядае выклік аператара ў зыходным кодзе). Аднак існуе шэраг абмежаванняў на перагрузку аператараў: нельга перагружаць аператары над прадвызначанымі (убудаванымі) тыпамі (скажам, пераазначаць множанне цэлых лікаў тыпу int); нельга выдумляць новыя аператары, якіх няма ў C++ (скажам, **); нельга змяняць меснасць (колькасць аргументаў) аператараў; прыярытэты аператараў захоўваюцца (скажам, у выразе a+b*c спачатку будзе выконвацца множанне, а потым складанне, якіх бы тыпаў ні былі a, b і c). Можна пераазначаць аператары [] (з адным параметрам) і () (з любым лікам параметраў).

namespace Foo \{
 const int x=5;
 typedef int\*\* T;
 void f(y) \{return y\*x\};
 double g(T);
 ...
\}

то па-за фігурнымі дужкамі мы павінны звяртацца да T, x, f, g як Foo::T, Foo::x, Foo::f, Foo::g. Калі мы ў нейкім файле жадаем звяртацца да іх непасрэдна, мы можам напісаць

using namespace Foo;

або

using Foo::T;

Прасторы імён патрэбны, каб не ўзнікала накладак паміж пакетамі, якія маюць глабальныя зменныя, функцыі ці тыпы з аднолькавымі імёнамі. Адмысловым выпадкам з’яўляецца безыменная прастора імён

namespace \{
 ...
\}

Усе імёны, азначаныя ў ёй, даступныя толькі ў бягучай адзінцы трансляцыі і больш нідзе.

struct Time \{
 int hh, mm, ss;
\};
Time t1, t2;
struct S \{
 typedef int\*\* T;
 T x;
\};
S::T y;

Аб’ектна-арыентаваныя асаблівасці мовы

Мова C++ дадае да Сі аб’ектна-арыентаваныя магчымасці. Яна уводзіць класы, якія забяспечваюць тры самыя важныя уласцівасці ААП: інкапсуляцыю, наследаванне і полімарфізм.

Існуе два значэнні слова клас. У шырокім сэнсе клас — гэта карыстальніцкі тып, аб’яўлены з выкарыстаннем аднаго з ключавых слоў class, struct ці union. У вузкім сэнсе клас — гэта карыстальніцкі тып, аб’яўлены з выкарыстаннем ключавога слова class.

Інкапсуляцыя (ахоўванне даных)

Асноўным спосабам уладкавання інфармацыі ў мове C++ з’яўляюцца класы. У адрозненне ад тыпу структура (struct) мовы Сі, якая можа складацца толькі з палёў і укладзеных тыпаў, клас (class) C++ можа складацца з палёў, укладзеных тыпаў і функцый-членаў (member functions). Члены класа бываюць адкрытымі (public), ахаванымі (protected) і закрытымі (private). У C++ тып структура падобны да тыпу клас, адрозненне ў тым, што па змаўчанні члены і наследаванне ў структуры адкрытыя, а ў класа — закрытыя.

З адкрытымі членамі класа можна рабіць ўсё, што заўгодна, як унутры так і звонку класа. Да закрытых жа членаў нельга звяртацца па-за класам; гэта зроблена адмыслова, каб не парушыць цэласнасць дадзеных класа. Спроба такога звароту выкліча памылку кампіляцыі. Да такіх членаў могуць звяртацца толькі функцыі-члены класа (а таксама так званыя функцыі-сябры і функцыі-члены класаў-сяброў; пра паняцце сяброў у C++ гл. ніжэй). Апроч адкрытых і закрытых членаў класа, могуць быць яшчэ і ахаваныя — гэта члены, даступныя свайму класу-ўладальніку, яго сябрам, а таксама вытворным ад яго класам (наследнікам). Такая ахова членаў называецца інкапсуляцыяй (або ахоўваннем даных).

Выкарыстоўваючы інкапсуляцыю, аўтар класа можа ахаваць свае дадзеныя ад няслушнага выкарыстання. Акрамя таго, ахоўванне ўкладзеных даных задумвалася для палягчэння сумеснай распрацоўкі класаў. Мелася на ўвазе, што пры змене спосабу захоўвання дадзеных, калі яны аб’яўлены як ахаваныя ці закрытыя, не патрабуецца адпаведных змен у класах, якія выкарыстоўваюць зменены клас. Напрыклад, калі ў старой версіі класа закрытыя ці ахаваныя дадзеныя захоўваліся ў выглядзе лінейнага спісу, а ў новай версіі — у выглядзе дрэва, не трэ будзе перапісваць ніякія функцыі, акрамя функцый-членаў класа, а таксама функцый-сяброў і функцый-членаў класаў-сяброў, а ў выпадку ахаваных членаў такіх жа функцый для вытворных класаў. З іншага боку, калі гэтыя дадзеныя былі адкрытымі, трэ будзе, увогуле кажучы, перапісваць усе функцыі, якія напрамую працуюць з гэтымі палямі: як члены любых класаў, так і функцыі, якія не з’яўляюцца членамі ніякіх класаў.

Доступprivate
(закрыты)
protected
(ахаваны)
public
(адкрыты)
Сам классёсцьёсцьёсць
Сябрыёсцьёсцьёсць
Наследнікінямаёсцьёсць
Па-за класамняманямаёсць

Выкарыстоўваючы ахоўванне даных, аднамерны масіў можна апісаць наступным чынам:

class Array \{
public:
 void Alloc(int new\_len);
 void Free();
 inline double Elem(int i);
 inline void ChangeElem(int i, double x);
protected:
 int len;
 double\* val;
\};

void Array::Alloc(int new\_len) 
 \{if (len>0) Free(); len=new\_len; val=new double[new\_len];\}
void Array::Free() \{delete [] val; len=0;\}
inline double Array::Elem(int i) 
 \{assert(i>=0 && i<len ); return val[i];\}
inline void Array::ChangeElem(int i, double x) 
 \{assert(i>=0 && i<len); val[i]=x;\}

І далей

Array a;
a.Alloc(10);
a.ChangeElem(3, 2.78);
double b = a.Elem(3);
a.Free();

Тут масіў a мае 4 адкрытыя функцыі-члены і 2 ахаваныя палі. Апісальнік inline падказвае кампілятару, што замест выкліку функцыі яе код варта падставіць у кропку выкліку. Часта гэтым можна дасягнуць большай эфектыўнасці.

Азначэнне функцый у целе класа

У целе класа можна апісаць толькі загаловак функцыі, а можна цалкам азначыць функцыю. У апошнім выпадку яна лічыцца ўбудавальнай (або падстаўляльнай) (inline), напрыклад:

class Array \{
public:
 void Alloc(int \_len) \{
 if (len == 0) Free();
 len = \_len;
 val = new double[len];
 \}

і гэтак далей.

Канструктары і дэструктары

Аднак у прыведзеным прыкладзе не развязана важная праблема: функцыі Alloc і Free па-ранейшаму трэба выклікаць уручную. Іншая праблема гэтага прыкладу — небяспечнасць аператара прысвойвання.

Каб развязаць гэтыя праблемы ў мову былі ўведзены канструктары і дэструктары. Канструктар выклікаецца кожны раз, калі ствараецца аб’ект дадзенага тыпу; дэструктар — пры знішчэнні. Пры пераўтварэннях тыпаў з удзелам асобнікаў (аб’ектаў) класаў таксама выклікаюцца канструктары і дэструктары.

З канструктарамі і дэструктарам клас выглядае так:

class Array \{
public:
 Array() : len(0), val(NULL) \{\}
 Array(int \_len) : len(\_len) \{val = new double[\_len];\}
 Array(const Array& a);
 ~Array() \{ Free(); \}
 inline double Elem(int i);
 inline void ChangeElem(int i, double x);
protected:
 void Alloc(int \_len);
 void Free();
 int len;
 double\* val;
\};

Array::Array(const Array& a) : len(a.len)
\{
 val = new double[len];
 for (int i=0; i<len; i++)
 val[i] = a.val[i];
\}

Тут Array::Array — канструктар, а Array::~Array — дэструктар. Канструктар капіравання Array::Array(const Array&) выклікаецца пры стварэнні новага аб’екта, які з’яўляецца копіяй ужо існуючага аб’екта. Зараз аб’ект класа Array нельга сапсаваць: як бы мы яго ні стваралі, што б мы ні рабілі, яго палі будуць несупярэчлівымі, таму што канструктар выклікаецца аўтаматычна. Усе небяспечныя аперацыі з указальнікамі схаваны ў закрытых функцыях-членах.

Array a(5); // выклікаецца Array::Array(int)
Array b; // выклікаецца Array::Array()
Array c(a); // выклікаецца Array::Array(const Array&)
Array d=a; // тое ж самае
b=c; // адбываецца выклік аператара =
 // калі ён не азначан (як у гэтым выпадку), то выклікаецца аператар прысвойвання па змаўчанні, які
 // ажыццяўляе капіраванне ўсіх падаб’ектаў і пачасткавае капіраванне нестатычных членаў-дадзеных.
 // як правіла канструктар капіравання і аператар прысвойвання перавызначаюцца парамі

Аператар new таксама выклікае канструктары, а delete — дэструктары.

Па змаўчанні, кожны клас мае няяўна аб’яўлены канструктар без параметраў, які будуе падаб’екты класаў-продкаў і задае палі класа, выклікаючы для іх канструктары па змаўчанні. Калі ў класе няма яўна аб’яўленага дэструктара, то клас мае няяўна аб’яўлены дэструктар.

Клас можа мець колькі заўгодна канструктараў (з рознымі наборамі параметраў), але толькі адзін дэструктар (у дэструктара не можа быць параметраў).

Іншыя магчымасці функцый-членаў

Функцыі-члены могуць быць і аператарамі:

class Array \{
...
 inline double &operator[] (int n)
 \{
 return val[n];
 \}

І далей

Array a(10);
...
double b = a[5];

Функцыі-члены (і толькі яны) могуць мець апісальнік const

class Array \{
...
 inline double operator[] (int n) const;

Такія функцыі не маюць права змяняць палі класа (акрамя палёў, пазначаных як mutable). Калі яны спрабуюць гэта зрабіць, кампілятар павінен выдаць паведамленне аб памылцы.

Наследаванне

Для стварэння класаў з дадатковай функцыянальнасцю ўводзяць наследаванне. Клас-наследнік мае палі і функцыі-члены класа-продка, але не мае права звяртацца да закрытых (private) палёў і функцый бацькоўскага класа. У гэтым і складаецца розніца паміж закрытымі і ахаванымі членамі.

Клас-наследнік можа дабаўляць свае палі і функцыі або пераазначаць функцыі-члены класа-продка.

Па змаўчанні, канструктар наследніка без параметраў выклікае канструктар класа-продка, а затым канструктары тых нестатычных членаў-дадзеных, якія з’яўляюцца асобнікамі пэўных класаў. Дэструктар працуе ў адваротным парадку. Канструктары класаў-наследнікаў даводзіцца азначаць кожны раз нанова. На шчасце, гэта можна зрабіць выклікам канструктара класа-продка.

class ArrayWithAdd : public Array \{
 ArrayWithAdd(int n) : Array(n) \{\}
 ArrayWithAdd() : Array() \{\}
 ArrayWithAdd(const Array& a) : Array(a) \{\}
 void Add(const Array& a);
\};

Наследнік змяшчае больш палёў і функцый-членаў чым продак, таму, калі наследаванне адкрытае, аб’екта класа-наследніка можна выкарыстоўваць усюды, дзе выкарыстоўваюцца асобнікі (аб’екты) класа-продка, але не наадварот.

Наследаванне бывае адкрытым, ахаваным і закрытым. Пры адкрытым наследаванні, адкрытыя і ахаваныя члены класа-продка захоўваюць свой узровень ахоўвання, а да закрытых не могуць звяртацца нават функцыі-члены наследніка. Ахаванае наследаванне адрозніваецца тым, што пры ім адкрытыя члены класа-продка з’яўляюцца ахаванымі членамі наследніка. Пры закрытым наследаванні ўсе члены класа-продка становяцца закрытымі членамі класа-наследніка; такім чынам, карыстальнік вытворнага класа не можа звяртацца да членаў бацькоўскага класа, нават калі яны аб’яўлены як адкрытыя. Клас-наследнік робіць іх закрытымі з дапамогай закрытага наследавання. Як правіла, адкрытае наследаванне ужываецца значна часцей за іншыя.

\Доступ к членам класа-продка
Узровень ахоўвання наследавання
закрыты член
(private)
ахаваны член
(protected)
адкрыты член
(public)
закрытае наследаванне
(private)
недаступнызакрыты
(private)
закрыты
(private)
ахаванае наследаванне
(protected)
недаступныахаваны
(protected)
ахаваны
(protected)
адкрытае наследаванне
(public)
недаступныахаваны
(protected)
адкрыты
(public)

Клас можа быць наследнікам некалькіх класаў. Такое наследаванне называецца множным наследаваннем. Такі клас валодае палямі і функцыямі-членамі ўсіх сваіх продкаў. Напрыклад, клас FlyingCat (ЛятучыКот) можа быць наследнікам класаў Cat (Кот) і FlyingAnimal (ЛятучаяЖывёла)

class Cat \{
 ...
 void Purr();
 ...
\};
class FlyingAnimal \{
 ...
 void Fly();
 ...
\};
class FlyingCat : public Cat, public FlyingAnimal \{
 ...
 PurrAndFly() \{Purr(); Fly();\}
 ...
\};

Полімарфізм (разнастайнасць падкласаў)

Полімарфізмам у праграмаванні завецца пераазначэнне наследнікам функцый-членаў базавага класа, напрыклад

class Figure \{
 ...
 void Draw() const;
 ...
\};

class Square : public Figure \{
 ...
 void Draw() const;
 ...
\};

class Circle : public Figure \{
 ...
 void Draw() const;
 ...
\};

У гэтым прыкладзе, якая з функцый будзе выклікана — Circle::Draw(), Square::Draw() ці Figure::Draw(), вызначаецца падчас кампіляцыі. Напрыклад, калі напісаць

Figure\* x = new Circle(0,0,5);
x->Draw();

то будзе выклікана Figure::Draw(), бо x — аб’ект класа Figure. Такі полімарфізм называецца статычным.

Але ў C++ ёсць і дынамічны полімарфізм, калі функцыя, якую трэба выклікаць, вызначаецца падчас выканання. Для гэтага функцыі-члены павінны быць віртуальнымі.

class Figure \{
 ...
 virtual void Draw() const;
 ...
\};

class Square : public Figure \{
 ...
 virtual void Draw() const;
 ...
\};

class Circle : public Figure \{
 ...
 virtual void Draw() const;
 ...
\};

Figure\* figures[10];
figures[0] = new Square(1, 2, 10);
figures[1] = new Circle(3, 5, 8);
...
for (int i = 0; i < 10; i++)
 figures[i]->Draw();

У гэтым выпадку для кожнага элемента будзе выклікана Square::Draw() ці Circle::Draw() у залежнасці ад фігуры.

Чыста віртуальнай функцыяй называецца віртуальная функцыя-член, якая аб’яўлена са апісальнікам = 0:

class Figure \{
 ...
 virtual void Draw() const = 0;
);

Чыста віртуальная функцыя можа быць пакінута без азначэння, акрамя выпадку, калі неабходна яе выклікаць.

Абстрактным класам называецца такі, у якога ёсць хоць адна чыста віртуальная функцыя-член. Аб’екты такіх класаў ствараць забаронена. Абстрактныя класы часта выкарыстоўваюцца як інтэрфейсы.

Сябры класа

Функцыі-сябры — гэта функцыі, якія не ёсць функцыямі-членамі, але маюць доступ да ахаваных і закрытых палёў і функцый-членаў класа. Яны павінны быць апісаны ў целе класа як friend. Напрыклад:

class Matrix \{
 ...
 friend Matrix Multiply(Matrix m1, Matrix m2);
 ...
\};

Matrix Multiply(Matrix m1, Matrix m2) \{
 ...
\}

Тут функцыя Multiply можа звяртацца да любых палёў і функцый-членаў класа Matrix.

Існуюць таксама класы-сябры. Калі клас A — сябар класа B, то ўсе яго функцыі-члены могуць звяртацца да любых палёў і функцый членаў класа B. Напрыклад:

class Matrix \{
 ...
 friend class Vector;
 ...
\};

Аднак у C++ не дзейнічае правіла «сябар майго сябра — мой сябар».

Па стандарце C++03 укладзены клас не мае доступу да закрытых членаў класа, які агортвае яго, і не можа быць аб’яўлен яго сябрам (апошняе вынікае з азначэння тэрміна сябар як нечлена класа). Аднак, многія пашыраныя кампілятары парушаюць абодва гэтыя правілы (відаць, з прычыны сукупнай дзіўнасці гэтых правіл).

Будучае развіццё

Бягучы стандарт мовы быў прыняты ў 2003 годзе. Наступная версія стандарту носіць неафіцыйную назву C++0x.

C++ працягвае развівацца, каб адказваць сучасным патрабаванням. Адна з груп, якія займаюцца мовай C++ у яе сучасным выглядзе і накіроўваюць камітэту па стандартызацыі C++ парады па яе паляпшэнні — гэта Boost. Напрыклад, адзін з кірункаў дзейнасці гэтай групы — удасканаленне магчымасцей мовы шляхам дабаўлення ў яе асаблівасцей метапраграмавання.

Стандарт C++ не апісвае спосабы наймення аб’ектаў, некаторыя падрабязнасці апрацоўкі выключэнняў і іншыя магчымасці, спалучаныя з асаблівасцямі рэалізацыі, што прыводзіць да несумяшчальнасці аб’ектнага кода, створанага рознымі кампілятарамі. Аднак, каб зняць гэту праблему, трэцімі асобамі было створана мноства стандартаў для розных архітэктур і аперацыйных сістэм.

Тым не менш (па стане на час напісання гэтага артыкула) сярод кампілятараў C++ усё яшчэ працягваецца бітва за поўную рэалізацыю стандарту C++, асабліва ў вобласці шаблонаў — часткі мовы, зусім нядаўна распрацаванай камітэтам стандартызацыі ў поўным аб’ёме.

Ключавое слова export

Адной са спрэчных пунктаў у гэтым пытанні з’яўляецца ключавое слова export, якое ўведзена з мэтай зняць патрэбу ў абавязковым папярэднім азначэнні шаблона[4].

Першым кампілятарам, які падтрымлівае export у шаблонах, стаў Comeau C++ напачатку 2003 года (праз пяць гадоў пасля выхаду стандарту). У 2004 годзе бета-версія кампілятара Borland C++ Builder X таксама ўключыла яго падтрымку.

Абодва гэтых кампілятара заснаваны на вонкавым інтэрфейсе EDG. Іншыя кампілятары, такія як Microsoft Visual C++ ці GCC (GCC 3.4.4), наогул не падтрымліваюць гэта ключавое слова. Хёрб Саттэр, сакратар камітэта па стандартызацыі C++, рэкамендаваў прыбраць export з будучых версій стандарту з прычыны сур’ёзных складанасцей у паўнавартаснай рэалізацыі, аднак у выніку яго вырашылі пакінуць.

Са спісу іншых праблем, спалучаных з шаблонамі, можна прывесці пытанні пабудовы частковай спецыялізацыі шаблонаў, якія дрэнна падтрымліваліся на працягу многіх гадоў пасля выхаду стандарту C++.

Стандартная бібліятэка

Асноўны артыкул: Стандартная бібліятэка ў C++ У склад стандартнай бібліятэкі C++ уваходзіць стандартная бібліятэка мовы Сі з невялікімі зменамі, якія робяць яе больш прыдатнай для мовы C++. Другім істотным складнікам бібліятэкі C++ ёсць Стандартная Бібліятэка Шаблонаў (STL). Яна дае такія важныя прылады, як тыпы-скрыні (або кантэйнеры) (напрыклад, вектары і спісы) і ітэратары (абагульненыя указальнікі), якія дазваляюць працаваць са тыпамі-скрынямі (кантэйнерамі) як з масівамі. Акрамя таго, STL дазваляе падобным чынам працаваць і з іншымі скрыневымі тыпамі (тыпамі кантэйнераў), напрыклад, слоўнікамі (асацыятыўнымі спісамі), стэкамі, чэргамі.

Выкарыстоўваючы шаблоны, можна пісаць абагульненыя алгарытмы, здольныя працаваць з любымі скрыневымі тыпамі (кантэйнерамі) ці паслядоўнасцямі, вызначанымі ітэратарамі.

Гэтак жа, як і ў Сі, доступ к магчымасцям бібліятэк ажыццяўляецца з дапамогай указання #include для ўключэння стандартных файлаў. Усяго ў стандарце C++ вызначана 50 такіх файлаў.

STL да ўключэння ў стандарт C++ была незалежнай распрацоўкай, напачатку — фірмы HP, а затым SGI. Стандарт мовы не называе яе «STL», бо гэта бібліятэка стала неад’емнай часткай мовы, аднак шмат хто і дагэтуль выкарыстоўвае гэту назву, каб адрозніваць яе ад астатняй часткі стандартнай бібліятэкі (патокі ўводу/вываду (iostream), падмноства Сі і інш.).

Праект пад назвай STLport[5], заснаваны на SGI STL, ажыццяўляе сталае абнаўленне STL, IOstream і радковых класаў. Некаторыя іншыя праекты таксама займаюцца распрацоўкай асобных дастасаванняў стандартнай бібліятэкі для розных канструктарскіх задач. Кожны вытворца кампілятараў C++ абавязкова пастаўляе якую-небудзь рэалізацыю гэтай бібліятэкі, бо яна з’яўляецца вельмі важнай часткай стандарту і шырока выкарыстоўваецца.

C++ не ўключае ў сябе Сі

Нягледзячы на тое, што вялікая частка кода Сі будзе слушнай і на мове C++, C++ не ёсць надмноствам мовы Сі і не ўключае яе ў сябе. Існуе і такі код, які слушны на Сі, але няслушны для C++. Гэта адрознівае яго ад Аб’ектнага Сі, яшчэ аднаго ўдасканалення Сі для ААП, які якраз і ёсць надмноствам Сі.

У прыватнасці крыніцай несумяшчальнасці з’яўляюцца новыя (адносна Сі) ключавыя словы. Так, апісанне пераменнай

 int try;

з’яўляецца цалкам слушным на Сі, але хібным на мове C++, бо слова try з’яўляецца ў C++ ключавым.

Існуюць і іншыя адрозненні. Напрыклад, C++ не дазваляе выклікаць функцыю main() усярэдзіне праграмы, у той час як у Сі гэта дзеянне правамернае. Акрамя таго, C++ стражэйшы ў некаторых пытаннях: напрыклад, ён не дапускае няяўнага прывядзення тыпаў паміж нязвязанымі тыпамі ўказальнікаў і не дазваляе выкарыстоўваць функцыі, якія яшчэ не аб’яўлены.

Да таго ж код, слушны на абедзвюх мовах, можа даваць розныя вынікі ў залежнасці ад таго, кампілятарам якой мовы ён апрацаваны. Напрыклад, на большасці платформ наступная праграма друкуе «C», калі кампілюецца кампілятарам Сі, і «C++» — калі кампілятарам C++. Так адбываецца з-за таго, што знакавыя канстанты ў Сі (напрыклад 'a') маюць тып int, а ў C++ — тып char, а памеры гэтых тыпаў звычайна адрозніваюцца.

#include <stdio.h>

int main()
\{
 printf("%s\n", (sizeof('a') == sizeof(char)) ? "C++" : "C");
 return 0;
\}

Прыклады праграм на C++

Прыклад № 1

Гэта прыклад праграмы, якая нічога не робіць. Яна пачынае выконвацца і адразу завяршаецца. Яна складаецца з асноўнага патоку: функцыі main(), якая пазначае кропку пачатку выканання праграмы на C++.

int main()
\{
 return 0;
\}

Стандарт C++ патрабуе, каб функцыя main() вяртала тып int. Праграма, у якой функцыя main() вяртае значэнне іншага тыпу, не адпавядае стандарту C++.

Стандарт не кажа пра тое, што насамрэч азначае вяртаймае значэнне функцыі main(). Традыцыйна яно вытлумачваецца як код вяртання праграмы. Стандарт гарантуе, што вяртанне 0 функцыяй main() паказвае, што праграма была завершана паспяхова.

Завяршэнне праграмы на C++ з памылкай традыцыйна пазначаецца шляхам вяртання ненулявога значэння.

Прыклад № 2

Гэта праграма таксама нічога не робіць, але карацейшая.

int main()\{\}

У C++, калі выкананне праграмы даходзіць да канца функцыі main(), гэта раўназначна return 0;. Для ўсіх астатніх функцый (акрамя main()) гэта не так.

Прыклад № 3

Гэта прыклад праграмы Hello World, якая выводзіць гэта знакамітае паведамленне, выкарыстоўваючы стандартную бібліятэку, і завяршаецца.

#include <iostream> // гэта неабходна для std::cout і std::endl
 
int main()
\{
 std::cout << "Hello, world!" << std::endl;
\}

Прыклад № 4

Сучасны C++ дазваляе развязваць простым спосабам і больш складаныя задачы. Гэты прыклад паказвае акрамя ўсяго іншага выкарыстанне тыпаў-скрыняў (кантэйнераў) стандартнай бібліятэкі шаблонаў (STL).

#include <iostream> // для выкарыстання std::cout
#include <vector> // для std::vector<>
#include <map> // для std::map<> і std::pair<>
#include <algorithm> // для std::for\_each()
#include <string> // для std::string

using namespace std; // выкарыстанне прасторы імён "std"

void display\_item\_count(pair< string const, vector<string> > const& person) \{
 // person — гэта пары двух аб’ектаў: person.first — гэта яго імя,
 // person.second — гэта спіс яго прадметаў (вектар радкоў)
 cout << person.first << " is carrying " << person.second.size() << " items" << endl;
\}

int main()
\{
 // аб’яўляем слоўнік (мапу, адлюстраванне) з радковымі ключамі і дадзенымі ў выглядзе вектараў радкоў
 map< string, vector<string> > items;

 // Дабавім у гэту карту некалькі чалавек і дадзім ім некалькі рэчаў
 items["Anya"].push\_back("scarf");
 items["Dimitri"].push\_back("tickets");
 items["Anya"].push\_back("puppy");

 // Перабяром усе аб’екты ў скрыні (кантэйнеры)
 for\_each(items.begin(), items.end(), display\_item\_count);
\}

У гэтым прыкладзе для прастаты выкарыстоўваецца ўказанне выкарыстанай прасторы імён з дапамогай ключавых слоў using namespace. Аднак у вялікіх прамысловых праграмах звычайна раяць выкарыстоўваць аб’яўленні асобных класаў і функцый, бо з-за магчымага супадзення імён у розных прасторах могуць узнікнуць шматлікія цяжка ўлоўныя памылкі. Таму лепш пісаць, напрыклад, так:

#include <vector>

int main()
\{
 using std::vector;

 vector<int> my\_vector;
\}

Тут дырэктыва (указанне) змешчана ў вобласць функцыі, што памяншае шанцы сутыкненняў імён (гэта і стала прычынай увядзення ў мову прастор імён). Ужыванне аб’яўленняў, якія зліваюць розныя прасторы імёнаў у адну, руйнуе сам замысел прасторы імён.

Прыклад № 5

Папулярныя бібліятэкі (напрыклад, boost) у спалучэнні са стандартнымі сродкамі мовы дазваляюць вельмі коратка і наглядна запісваць код. У прыведзеным ніжэй прыкладзе вылічаецца скалярны здабытак вектараў няцотных лікаў і квадратаў. У кодзе вектары значэнняў прадстаўлены STL-падобнымі паслядоўнасцямі.

#include <iostream>
#include <numeric>
#include <boost/iterator/counting\_iterator.hpp>
#include <boost/iterator/transform\_iterator.hpp>

int odd(int i)
\{
 return 2 \* i + 1;
\}

int square(int i)
\{
 return i \* i;
\}

typedef boost::counting\_iterator <int> counter;
typedef boost::transform\_iterator <int (\*)(int), counter> transformer;

transformer odds(int n)
\{
 return transformer(counter(n), odd);
\}

transformer squares(int n)
\{
 return transformer(counter(n), square);
\}

int main()
\{
 using namespace std;

 cout << "Enter vector length: ";
 int n; cin >> n;

 cout << inner\_product( odds(0), odds(n), squares(0), 0 ) << endl;
\}

Гэты прыклад паказвае так званы «плоскі» стыль запісу. Гэта назва звязана з тым, што алгарытмы STL дазваляюць запісваць код без цыклаў, адпаведна шырыня водступаў у адфарматаваным кодзе не дужа змяняецца. Прыхільнікі такога падыходу лічаць, што праграмісту, знаёмаму са стандартнай бібліятэкай C++, дастаткова радка з выклікам inner_product(), каб зразумець, што робіць праграма. З гэтага пункту гледжання выклік inner_product блізкі да славеснага апісання задачы: «вылічыць скалярны здабытак вектараў няцотных лікаў і квадратаў для значэнняў ад нуля да n».

Параўнанне C++ з мовамі Java і C#

Мэтай стварэння C++ было пашырэнне магчымасцей Сі, найбольш распаўсюджанай мовы сістэмнага праграмавання. Накіраваная на той жа абсяг ужытку, што і мова Сі, мова C++ пераняла ад яе ў спадчыну мноства не самых лепшых, з тэарэтычнага пункту гледжання, асаблівасцей. Пералічаныя вышэй прынцыпы, якіх прытрымліваўся аўтар мовы, прадвызначылі многія недахопы C++.

У галіне прыкладнога праграмавання альтэрнатывай C++ стала мова Java. Нягледзячы на пераемнасць у адносінах да C++, Java будавалася на прынцыпова іншай аснове, яе распрацоўшчыкі не былі абмежаваны патрабаваннямі сумяшчальнасці з мовай-продкам і забеспячэння найбольшай дасягальнай эфектыўнасці, дзякуючы гэтаму яны змаглі карэнным чынам перапрацаваць мову, адмовіцца ад мноства сінтаксічных сродкаў, каб дамагчыся ідэалагічнай цэласнасці мовы. Пазней фірма Майкрасофт прапанавала мову C#, якая ўяўляе сабой яшчэ адну перапрацоўку мовы C++ у тым жа кірунку, што і Java. Пасля з’явілася мова Nemerle, у якой да сродкаў C# далучаны сродкі функцыйнага праграмавання. Яшчэ пазней з’явілася спроба аб’яднання эфектыўнасці C++ з бяспекай і хуткасцю распрацоўкі Java і C# — была прапанавана мова D, якая пакуль не атрымала шырокага прызнання.

Java і C++ можна разглядаць як дзве мовы-пераемніцы Сі, распрацаваныя з розных меркаванняў, у выніку чаго іх шляхі разышліся. У гэтай сувязі цікава параўнаць гэтыя мовы (усё, сказанае ніжэй пра Java, можна з аднолькавым поспехам аднесці да моў C# і Nemerle, бо на такім узроўні разглядання гэтыя мовы адрозніваюцца толькі вонкава).

СінтаксісC++ захоўвае сумяшчальнасць з C, наколькі гэта магчыма. Java захоўвае вонкавае падабенства да C і C++, але, у рэчаіснасці, моцна адрозніваецца ад іх — з мовы выдалена вялікая колькасць сінтаксічных сродкаў, абвешчаных неабавязковымі. У выніку праграмы на Java бываюць больш грувасткія ў параўнанні з іх аналагамі на C++. З іншага боку, Java прасцешая за C++, што палягчае як вывучэнне мовы, так і стварэнне транслятараў для яе. Выкананне праграмыJava-код кампілюецца ў прамежкавы код, які ў далейшым інтэрпрэтуецца ці кампілюецца, тады як мова C++ першапачаткова скіравана на кампіляцыю ў машынны код для пэўнай платформы (хоць, тэарэтычна, нішто не перашкаджае стварыць для C++ транслятар у прамежкавы код). Ужо гэта вызначае розніцу ў абласцях ужытку моў: мову Java наўрад ці можна выкарыстаць пры напісанні такіх адмысловых праграм, як драйверы прыстасаванняў ці нізкаўзроўневыя сістэмныя ўтыліты. Дзякуючы механізму выканання, напісаныя на Java праграмы, нават адкампіляваныя (у байт-код), цалкам пераносныя. Стандартнае асяроддзе і асяроддзе выканання дазваляюць выконваць праграмы на Java на любой апаратнай платформе і ў любой АС, без якіх-небудзь змен, намаганні па пераносе праграм мінімальныя (а пры выкананні парад па стварэнні пераносных праграм — і зусім нулявыя). Коштам пераноснасці становіцца страта эфектыўнасці — праца асяроддзя выканання прыводзіць да дадатковых накладных выдаткаў. Кіраванне рэсурсаміC++ дазваляе выкарыстоўваць прынцып «захоп рэсурсаў шляхам ініцыялізацыі» (RAII), пры якім рэсурсы спалучаюцца з аб’ектам і аўтаматычна вызваляюцца пры разбурэнні аб’екта (напрыклад, std::vector і std::ifstream). Таксама магчымы падыход, калі праграміст, выдзяляючы рэсурсы (памяць пад аб’екты, адкрытыя файлы і т. п.), абавязаны яўна паклапаціцца пра своечасовае іх вызваленне. Java працуе ў асяроддзі са зборкай смецця, якая аўтаматычна адсочвае спыненне выкарыстання аб’ектаў і вызваляе занятую імі памяць, калі ў гэтым ёсць неабходнасць, у некаторы нявызначаны момант часу. Ручное кіраванне мае перавагі ў сістэмным праграмаванні, дзе патрэбен поўны кантроль над рэсурсамі, а RAII і зборка смецця зручнейшыя ў прыкладным праграмаванні, бо ў значнай ступені вызваляюць праграміста ад неабходнасці адсочваць, калі рэсурсы больш не выкарыстоўваюцца. Зборшчык смецця Java патрабуе сістэмных рэсурсаў, што змяншае эфектыўнасць выканання праграм, пазбаўляе праграмы на Java прадвызначанасці выканання, акрамя таго ён здольны сачыць толькі за памяццю. Файлы, каналы, гнёзды (сокеты), аб’екты графічнага інтэрфейсу праграміст на Java заўсёды вызваляе яўна. Стандартызацыя асяроддзяУ Java ёсць дакладна вызначаныя стандарты на ўвод-вывад, графіку, геаметрыю, дыялог, доступ к базам дадзеных і іншым тыпавым прыкладанням. У гэтых пытаннях у мове C++ значна больш свабоды. Стандарты на графіку, доступ к базам дадзеных і г. д. з’яўляюцца недахопам, калі праграміст жадае вызначыць свой уласны стандарт. УказальнікіC++ захоўвае магчымасць працы з нізкаўзроўневымі ўказальнікі. У мове Java ўказальнікаў няма. Выкарыстанне ўказальнікаў часта ёсць прычынаю цяжка ўлоўных памылак, але праца з указальнікамі неабходна для нізкаўзроўневага праграмавання. У прынцыпе, C++ валодае наборам сродкаў (канструктары і дэструктары, стандартныя шаблоны, спасылкі), якія дазваляюць амаль цалкам выключыць ручное выдзяленне і вызваленне памяці і небяспечныя аперацыі з указальнікамі. Аднак такое выключэнне патрабуе пэўнай культуры праграмавання, у той час як у мове Java яно рэалізуецца аўтаматычна. Парадыгма праграмаванняУ адрозненне ад C++, Java з’яўляецца чыста аб’ектна-арыентаванай мовай, без магчымасці працэдурнага праграмавання. Каб аб’явіць проста функцыю ці глабальную зменную у Java неабходна ствараць фіктыўныя класы, якія змяшчаюць толькі статычныя (static) члены [6]. Для задання галоўнай функцыі нават самай простай праграмы на Java неабходна змясціць яе ў клас [7]. Дынамічная інфармацыя пра тыпыу C++ “дынамічнае атаясамленне тыпаў даных” (RTTI) абмежавана магчымасцю параўноўваць тыпы аб’ектаў паміж сабой і з літаральнымі значэннямі тыпаў. У сістэме Java даступна больш падрабязная інфармацыя пра тыпы. Гэту магчымасць можна было б рэалізаваць у C++, маючы поўную інфармацыю пра тыпы падчас кампіляцыі (“атаясамленне тыпаў даных падчас кампіляцыі” CTTI). Папярэдняя апрацоўка (прэпрацэсар)C++ выкарыстоўвае прэпрацэсар для ўключэння азначэнняў функцый і класаў, для падключэння бібліятэк, цалкам выкананых у зыходным кодзе, а таксама дазваляе ажыццяўляць метапраграмаванне з выкарыстаннем прэпрацэсара, якое, у прыватнасці, развязвае складаныя праблемы высокаўзроўневага паўтарэння кода[8]. Ёсць меркаванне, што гэты механізм небяспечны, бо імёны макрасаў прэпрацэсара глабальныя, а самі макрасы амаль ніяк не звязаны з пабудовамі самой мовы. Гэта можа прыводзіць да складаных супярэчнасцей імёнаў. З іншага пункту гледжання, C++ дае дастатковыя сродкі (канстанты, шаблоны, убудавальныя функцыі) для таго, каб амаль цалкам выключыць выкарыстанне прэпрацэсара. Java выключыла прэпрацэсар цалкам, пазбавіўшыся за раз ад усіх праблем з яго выкарыстаннем, але і страціўшы пры гэтым магчымасці метапраграмавання прэпрацэсара і тэкставых замен у кодзе сродкамі мовы. Адрозненні моў прыводзяць да разлютаваных спрэчак паміж прыхільнікамі дзвюх моў пра тое, якая мова лепшая. Спрэчкі гэтыя шмат у чым беспрадметныя, бо прыхільнікі Java лічаць, што адрозненні сведчаць на карысць Java, а прыхільнікі C++ мяркуюць адваротнае. Некаторыя довады з часам састарэлі, напрыклад, папрокі ў неэфектыўнасці Java з-за наяўнасці асяроддзя выканання, якія былі справядлівымі ў першай палове 1990-х гадоў, у выніку лавінападобнага росту прадукцыйнасці камп’ютараў і з’яўлення больш эфектыўнай тэхнікі выканання (JIT) у значнай меры страцілі актуальнасць. Мова C++, у сваю чаргу, развівалася, і шэраг яе недахопаў выпраўлены ў апошніх версіях стандарту (напрыклад, з’явіўся механізм частковай спецыфікацыі шаблонаў).

Далёка не ўсе праграмісты з’яўляюцца прыхільнікамі толькі аднае з моў. Паводле меркавання большасці праграмістаў, Java і C++ не з’яўляюцца канкурэнтамі, таму што ў іх розныя вобласці ўжытку. Іншыя лічаць, што выбар мовы для большасці задач з’яўляецца пытаннем асабістага густу.

Добрыя якасці і недахопы мовы

Перш за ўсё, неабходна падкрэсліць, што ацэньваць добрыя якасці і, асабліва, недахопы C++ неабходна з улікам тых прынцыпаў, на якіх будавалася мова, і патрабаванняў, якія да яе першапачаткова прад’яўляліся.

Добрыя якасці

C++ — надзвычай магутная мова, якія мае сродкі для стварэння эфектыўных праграм амаль любога прызначэння, ад нізкаўзроўневых утыліт і драйвераў да складаных праграмных комплексаў самага рознага прызначэння. У прыватнасці:

Недахопы

Большасць сваіх недахопаў мова C++ атрымала ў спадчыну ад мовы-продка — Сі, — і выкліканы яны першапачаткова пастаўленым патрабаваннем як мага большай сумяшчальнасці з Сі. Гэта такія недахопы, як:

Да ўласных недахопаў C++ можна аднесці:

Гл. таксама

Зноскі


  1. Страўструп Б. 2.1. Что такое C++? // Язык праграммирования C++. Указ. соч. — С. 57.
  2. 1 2 3
    Страуструп Б. 1.4. Исторические замечания // Язык программирования C++. Указ. соч. — С. 46.

  3. Страуструп Б. Дизайн і эволюция C++ = The Design and Evolution of C++. — Спб.: Піцер, 2007. — 445 с. — ISBN 5-469-01217-4.
  4. Гл. артыкул “Як ключавое слова export мовы C++ дапамагае пры памылцы звязвання шаблонаў”
  5. http://www.stlport.org/
  6. Class Arrays, JavaTM 2 Platform Std. Ed. v1.4.2 Архівавана 7 мая 2010.
  7. The Java ™ Tutorials. A Closer Look at the «Hello World!» Application
  8. З “C++ Template Metaprogramming, " by David Abrahams and Aleksey Gurtovoy. Copyright (c) 2005 by Pearson Архівавана 29 студзеня 2010.

  9. Цяжка знайсці пачаткоўца (і не толькі), які хоць раз (а часам і не раз) не напароўся б на гэту жорсткую, каварную, бязглуздую і бязлітасную памылку :)))
  10. The Java ™ Tutorials: The switch Statement
  11. MSDN: The switch statement in C#

  12. Dave Gottner. Templates Without Code Bloat // Dr. Dobb’s Journal. — студзень 1995.

  13. Adrian Stone.. Minimizing Code Bloat: Redundant Template Instantiation (нявызн.). Game Angst (22 верасня 2009). Праверана 19 студзеня 2010.

  14. Herb Sutter. C++ Conformance Roundup // Dr. Dobb’s Journal. — студзень 2001.
  15. Are there any compilers that implement all of this? (нявызн.) (недаступная спасылка). comp.std.c++ frequently asked questions / The C++ language. Comeau Computing (англ.) (10 снежня 2008). Архівавана з першакрыніцы 30 красавіка 2009. Праверана 19 студзеня 2010.

  16. vanDooren.. C++ keyword of the day: export (нявызн.). Blogs@MSMVPs (24 верасня 2008). — «The export keyword is a bit like the Higgs boson of C++. Theoretically it exists, it is described by the standard, and noone has seen it in the wild. … There is 1 C++ compiler front-end in the world which actually supports it»  Праверана 19 студзеня 2010.

  17. Scott Meyers.. Code Bloat due to Templates (нявызн.). comp.lang.c++.moderated. Usenet (16 мая 2002). Праверана 19 студзеня 2010.
  18. TIOBE Programming Community Index for January 2010 Архівавана 2 ліпеня 2013.
  19. Boehm-Demers-Weiser garbage collector for C and C++ Архівавана 21 студзеня 2012.

Літаратура

Спасылкі

Артыкулы і кнігі, бібліятэкі матэрыялаў па C++

Форумы

Класы, бібліятэкі

Асяроддзі распрацоўкі

Тэмы гэтай старонкі (5):
Катэгорыя·Мовы праграмавання
Катэгорыя·З’явіліся ў 1983 годзе
Катэгорыя·C++
Катэгорыя·Мовы праграмавання паводле алфавіта
Катэгорыя·Старонкі з няправільным сінтаксісам спасылак на крыніцы