C++

[մինի|[Բյորն Ստրաուստրուպը C++ ծրագրավորման լեզվի ստեղծողը]]
**C++** (արտասանվում է ինչպես *սի փլաս փլաս* ) ընդհանուր նշանակության ծրագրավորման լեզու, որը համարվում է «միջին-մակարդակի» լեզու, քանի որ թույլատրում է ինչպես ցածր մակարդակի, այնպես էլ բարձր մակարդակի ծրագրավորում։ Այն ստատիկորեն տիպավորվող, բազմապիսի մոտեցումներ թույլատրող (multi-paradigm), սովորաբար կազմակվող (կոմպիլյացվող) լեզու է։

Բյորն Ստրաուստրուպը, ստեղծեց C++ լեզուն Bell Labs-ում 1979 թ.-ին, որպես C ծրագրավորման լեզվի բարելավում և անվանեց այն «*C with Classes»*: 1983 թ.-ին այն վերանվանվեց C++ -ի։

C++ -ը ամենատարածված ծրագրավորման լեզուներից է։ Կիրառման ոլորտներից են համակարգային ծրագրավորումը, կիրառական ծրագրերի ստեղծումը, ֆիզիկական սարքավորումների՝ օպերացիոն համակարգի հետ կապի ապահովման ծրագրերի ստեղծումը, բարձր արդյունավետությամբ աշխատող սերվեր և օգտագործող ծրագրերի ստեղծումը, ինչպես նաև, ներդրված ծրագրերի և համակարգչային խաղերի ստեղծումը։

## Պատմություն

### Ստեղծում
Լեզուն առաջացել է 1980-ական թվականների սկզբին, երբ Bell Labs ընկերության աշխատակից Բյորն Ստրաուստրուպը սեփական կարիքների համար մի շարք կատարելագործումներ մտածեց C ծրագրավորման լեզվի համար։ Երբ 1970-ականների վերջում Ստրաուստրուպը սկսեց աշխատել Bell Labs-ում հաջորդականությունների տեսության առաջադրանքների վրա (հեռախոսների մոդելավորման հավելվածում), նա բացահայտեց, որ այդ ժամանակ գոյություն ունեցող մոդելավորման լեզուների կիրառման փորձերը արդյունավետ չէին, իսկ բարձր արդյունավետություն ունեցող մեքենայական լեզուների կիրառումը չափազանց բարդ է՝ նրանց սահմանափակ արտահայտչականության պատճառով։ Այսպես, Սիմուլա (ծրագրավորման լեզու) լեզուն ունի այնպիսի հնարավորություն, որ մեծ ծրագրային ապահովման մշակման ժամանակ բավականին օգտակար կլինի, սակայն այն շատ դանդաղ է աշխատում։ Իսկ BCPL լեզուն բավականին արագ է աշխատում, սակայն շատ մոտ է ցածր մակարդակի լեզուներին և չի կարող կիրառվել մեծ ծրագրային ապահովում մշակման ժամանակ։

Հիշելով ատենախոսության իր փորձը, Ստրաուստրուպը որոշեց ավելացնել C լեզվի (որի իրավահաջորդը BCPL-ն է) հնարավորությունները, մատչելի Սիմպուլա լեզվով։ C լեզուն, լինելով հիմնարար լեզուն UNIX համակարգի, որի վրա աշխատել են Bell համակարգիչները, արագ են, բազմաֆունկցիոնալ և շարժական։ Ստրաուստրուպը ավելացրել էր հնարավորություն տալիս աշխատել դասերով և օբյեկտներով։ Արդյունքում գործնական խնդիրները մոդելավորման դարձավ մատչելի լուծելու ինչպես ժամանակի տեսանկյունից մշակման (շնորհիվ օգտագործման Սիմպուլա-նման դասերի), այնպես էլ ժամանակի տեսանկյունից հաշվարկներով (շնորհիվ արագ աշխատող C-ի)։ Առաջին հերթին C է եղել ավելացվել դասեր (ինկափսուլացիայով), դասերի ժառանգումը, խիստ ձևերի ստուգում, inline-գործառույթները և default փաստարկները։ Վաղ լեզվի տարբերակը, սկզբնապես անվանվել էր «C with classes» («Սի դասերով»), դարձավ հարսանելի 1980 թվականից։

Մշակելով *C դասով*, Ստրաուստրուպ գրեց cfront ծրագիրը - տրանսյլատոր, վերամշակման հենակետային կոդը *C-ն դասով* հենակետային կոդում պարզապես C:
Որը թույլ տվեց աշխատել լեզվի հետ և օգտագործել այն պրակտիկայում, կիրառելով նախապես գոյություն ունեցող UNIX-ի ենթակառուցվածքը C-ն մշակելու համար։ Նոր լեզուն, անսպասելի էր հեղինակի համար, ձեռք բերեց մեծ տարածվածություն իր գործընկերների շրջանում և շուտով Ստրաուստրուպը չի կարող անձամբ աջակցել դրան, պատասխանեց մոտ հազար հարցի։

1983 թ. լեզվում ավելացվեց նոր հնարավորություններ, ինչպիսիք են. վիրտուալ ֆունկցիաները, ֆունկցիաների և օպերատորների գերբեռնվածությունը, հղումները, հաստատունները, օգտվողի վերահսկողությունը ազատ հիշողության կառավարման, բարելավվել էր ձևի ստուգումը և նոր ոճ (`//`) մեկնբանություններին։ Ստացված լեզուն արդեն դադարեց պարզապես լինել լրացվաց տարբերակ դասական C-ին և վերանվանվեց *C-ն դասերով* ից «C++»: Առաջին կոմերցիոն թողարկումը եղել է 1985 թվականի հոկտեմբերին։

Սկզբում օֆիցիալ լեզվի ստանդարտացման զարգացումը հիմնականում եղել է Ստրաուստրուպի ուժերով ի պատասխան ծրագրավորման հասարակությանը։ Ստանդարտ լեզվի ֆունկցիաների նկարագրություններ, գրել է Ստրաուստրուպը C++-ի աշխատանքները հրապարակելուց (լեզվի նկարագրությունը, հղումը ուղեցույցը և այլն)։ Միայն 1998 թվականին վավերացվեց C++ լեզվի միջազգային ստանդարտը՝ ISO/IEC 14882:1998 «Standard for the C++ Programming Language»; հետո 2003 թվականին ստանդարտի տեխնիկական ուղղումները կատարելուց - ստեղծվեց ստանդարտի հաջորդ տարբերակը - ISO/IEC 14882:2003:

### Ստեղծման նպատակ
C++ լեզուն ստեղծելիս Բյորն Ստրաուստրուպն ուզում էր անել հետևյալը.

* Ստանալ ունիվերսալ լեզու իր ստատիկ տիպերով, որը կլինի էֆետկտիվ և C լեզվի հետ համատեղելի
* Անմիջականորեն և բոլոր հնարավոր տարբերակով ապահովել ծրագրավորման բազմաթիվ ոճեր, այդ թվում պրոցեդուրային ծրագրավորումը, տվյալների աբստրակցիան, օբյեկտ կողմնորոշված ծրագրավորումը և ջեներիկ ծրագրավորումը
* Ծրագրավորողին տալ ազատ ընտրության իրավունք, եթե անգամ ծրագրավորողը սխալ գործի
* Մաքսիմում կերպով ապահովել C լեզվի հետ համատեղելիությունը՝ դրանով իսկ ապահովելով հարկ եղած դեպքում C լեզվի անցմանը
* Խուսափել C և C++ լեզուների միջև եղած տարաձայնություններից. ցանկացած կոնստրուկցիա, որ կա երկու լեզուներում պետք է նշանակի միևնույն բանը և ունենա միևնույն ծրագրային վարքագիծը
* Խուսափել ոչ ունիվերսալ կամ ծրագրավորման հարթակների ընտրության հետ կապված հատկություններից
* «Չվճարել նրա համար, ինչը չի օգտագործվում». ոչ մի ծրագրավորման լեզու չպետք է գցի ծրագիրն աշխատելու արագությունը ոչ օգտագործված ծրագրային կոդի պատճառով
* Չպահանջել շատ բարդ ծրագրավորման միջավայր

### C լեզվի ընտրության նպատակահարմարություն
C լեզվի ընտրությունը որպես նոր ծրագրավորման լեզվի բազա պայմանավորված է նրանով, որ C լեզուն.

Չնայած C լեզվի մի շարք թերությունների, Ստրաուստրուպն ընտրեց C լեզուն, քանի որ այդ թերություններն արդեն հայտնի են, իսկ նոր ստեղծված ծրագիրն անկասկած կունենա իր թերությունները, որոնք դեռ պետք է բացահայտել։ Բացի այդ դա թույլ տվեց արագորեն կոմպիլյատոր (cfront) ստանալ, որը պարզապես նոր ավելացված սինտաքսային տարրերը տրանսլյացիա էր անում օրիգինալ C լեզվի։

C++ լեզուն զարգացնելու ժամանակ լեզվում ներառնվեցին միջոցներ, որոնք ծածկում էին C լեզվի կոնստրուկտիվ հնարավորությունները։ Այդ պատճառով էլ բազմաթիվ անգամ առաջարկներ եղավ վերացնել C լեզվի հետ համատեղելիությունը։ Այսպես թե այնպես համատեղելիություն նպատակահարմար եղավ թողնել, իսկ թողնելու պատճառները հետևյալն են.
* պահպանել C լեզվում գրված կողը, որը տեղափոխվել է C++
* բացառել այն ծրագրավորողների վերաուսուցումը, ովքեր նախկինում աշխատել են C լեզվով (նրանց մնում է միայն սովորել C++ լեզվի նոր հնարքները)
* բացառել խառնաշփոթը C և C++ լեզուների համատեղ օգտագործման ժամանակ («եթե երկու լեզուներ օգտագործվում են միաժամանակ, ապա նրանց տարբերությունը պետք է լինի մինիմալ, կամ այնքան մեծ, որ հնարավոր չլինի հնարավորությունները խառնել իրար»)

1983 թ.-ին լեզվին ավելացվեցին նոր հատկություններ՝ վիրտուալ ֆունկցիաներ, ֆունկցիաների և օպերատորների վերբեռնում, հղումներ, հաստատուններ, ազատ հիշողության օգտագործման կառավարում օգտատիրոջ կողմից և մեկնաբանության նոր ոճ (`//`)։ Ստացված լեզուն դատարեց C լեզվի վրա լոկ հավելումներով տարբերակ լինելուց և նրան «կլասներով C լեզվից» վերանվանեցին «C++»: Լեզվի առաջին կոմերցիոն թողարկումը լույս տեսավ 1985 թ.-ին։

Լեզվի անունն արյունքում ստացվեց ունար պոստֆիքս «ինկրեմենտից» `++` (արժեքի մեծացում մեկ միավորով)։ C+ անվանումը նրա համար չի օգտագործվել, քանի որ C լեզվի տեսանկյունից այն սխալ է պարունակում։ Բացի դրանից նպատակահարմար չէր լեզուն վերանվանել D, քանի նորաստեղծ լեզուն իրենից ներկայացնում էր C լեզվի ընդլայնված տարբերակը։

### Ստանդարտների պատմություն
1985 թվականին լույս տեսավ «C++ ծրագրավորման լեզու» գրքի առաջին հրատարակությունը, որն այդ լեզվի առաջին նկարագրությունն էր։ Այն կարևոր դեր խաղաց լեզվի հետագա զարգացման վրա, քանի որ լեզվի պաշտոնական ստանդարտ դեռևս գոյություն չուներ։ 1989 թվականին թողարկվում է C++-ի 2.0 տարբերակը։ Նրա նոր հնարավորությունները իրենց մեջ ներառում էին բազմակի ժառանգումը, աբստրակտ դասերը, ստատիկ ֆունկցիա–անդամները, ֆունկցիա–հաստատունները և պաշտպանված անդամները։ 1990 թվականին լույս է տեսնում «C++–ի մեկնաբանված տեղեկատվական ուղեցույց» գիրքը, որը հետագայում ստանդարտի համար որպես հիմք է ծառայել։ Վերջին թարմացումները ներառում էին կաղապարները, բացառությունները, անվանատարածքները, տիպերի վերման նոր եղանակները և բուլյան տիպը։

C++ լեզվի հետ միաժամանակ զարգանում էր նաև նրա ստանդարտ գրադարանը։ C++–ի ստանդարտ գրադարանի առաջին հավելումներն էին մուտքի–ելքի հոսքերը, որոնք ապահովում էին C լեզվի ավանդական `printf` և `scanf` ֆունկցիաների փոխարինման նոր միջոցներ։ Ավելի ուշ, ստանդարտ գրադարանի ամենանշանակալից զարգացումը դարձավ Կաղապարների ստանդարտ գրադարանի ներառումը։

1998 թվականին հրատարակվեց լեզվի ISO/IEC 14882:1998 ստանդարտը (հայտնի է որպես C++98), որն մշակվել էր C++–ի ստանդարտավորման հանձնաժողովի կողմից (ISO/IEC JTC1/SC22/WG21 working group)։ C++–ի ստանդարտը չի նկարագրում օբյեկտների անվանման եղանակները, բացառությունների մշակման որոշ մանրամասներ և այլ հնարավորություններ, որոնք ավելի շատ կապված են իրականացման մանրամասների հետ, որը տարբեր կոմպիլյատորների կողմից ստեղծված օբյեկտային կոդերը միմյանց միջև դարձնում է անհամատեղելի։ Սակայն դրա համար երրորդ դեմքերի կողմից ստեղծվել են բազմաթիվ ստանդարտներ որոշակի կառուցվածքների և օպերացիոն համակարգերի համար։

2003 թվականին հրապարակվեց լեզվի ISO/IEC 14882:2003 ստանդարտը, որտեղ ուղղված էին լեզվի նախորդ ստանդարտի բացահայտված սխալներն ու թերությունները։

2005 թվականին թողարկվեց Library Technical Report 1 (կարճ անվանումով՝ TR1) հաշվետվությունը։ Չհանդիսանալով պաշտոնական ստանդարտի մի մաս, հաշվետվությունը նկարագրում է ստանդարտ գրադարանի ընդլայնումներ, որոնք, համաձայն հեղինակների սպասելիքների, C++ լեզվի հաջորդ տարբերակներում պետք է ներառվեն։ TR1-ի աջակցման աստիճանը բարելավվում է C++ լեզվի համարյա թե բոլոր աջակցվող կոմպիլյատորներում։

2009 թվականից սկսած աշխատանք էր տարվում նախորդ ստանդարտի թարմացման ուղղությամբ։ Սկզբում նոր ստանդարտի նախնական տարբերակն էր C++99-ը, իսկ մեկ տարի անց C++0x-ը, այսօր՝ C++11-ը, որտեղ ներառված էին լեզվի միջուկի հավելումներ և ստանդարտ գրադարանի ընլայնումներ, այդ թվում՝ TR1-ի մեծ մասը։

C++-ը շարունակում է զարգանալ, որպեսզի բավարարի ժամանակակից պահանջներին։ C++ լեզուն մշակող և ստանդարտավորման հանձնաժողովին լեզվի բարելավմանը նպաստող առաջարկներ ներկայացնող խմբերից մեկը Boost-ն է, որն, այդ թվում, զբաղվում է նաև լեզվի հնարավորությունների կատարելագործմամբ՝ լեզվում ավելացնելով մետածրագրավորման առանձնահատկությունները։

Ոչ մեկ չունի C++ լեզվի նկատմամբ ավելի շատ իրավունքներ, քան մյուսները․ այն ազատ է։ Սակայն լեզվի ստանդարտի փաստաթուղթը անվճար հասանելի չէ (բացառությամբ ստանդարտների սևագրերը)։

## Լեզվի տեսք
C++–ի 2003 թվականի ստանդարտը կազմված է երկու հիմնական մասերից՝ լեզվի միջուկի նկարագրությունից և ստանդարտ գրադարանների նկարագրությունից։

Բացի այդ, գոյություն ունեն մեծ թվով C++–ի գրադարաններ, որոնք չեն մտնում տվյալ ստանդարտի մեջ։ C++–ով գրված ծրագրերում կարելի է օգտագործել C լեզվի շատ գրադարաններ։

Ստանդարտացումն սահմանում է C++ ծրագրավորման լեզուն, սակայն C++ անվանման ետևում կարող են թաքնված լինել նաև լեզվի ոչ լիարժեք, սահմանափակ, մինչ ստանդարտային տարբերակներ։ Սկզբնական շրջանում լեզուն զարգանում էր առանց ձևական շրջանակների, ինքնաբերաբար, իր առջև դրված խնդիրների սահմաններում։ Լեզվի զարգացումն ուղեկցվել է cfront կոմպիլյատորի զարգացմամբ։ Լեզվի նորամուծություններին համընթաց փոփոխվում էր նաև cfront–ի տարբերակի համարը։ Կոմպիլյատորի այդ համարը տարածվում էր նաև լեզվի վրա, սակայն այսօր C++ լեզվի տարբերակների մասին չեն խոսում։

### Ոչ օբյեկտ կողմնորոշված հնարավորություններ
Այս բաժնում նկարագրվում են հնարավորություններ, որոնք անմիջականորեն կապված չեն օբյեկտ կողմնորոշված ծրագրավորման (ՕԿԾ) հետ, բայց որոնցից շատերը կարևոր դեր են խաղում ՕԿԾ–ի կիրառման ժամանակ։

#### Մեկնաբանություններ
C++–ն աջակցում է մեկնաբանություններ ինչպես C լեզվի ոճով՝

```cpp
/*
 Սա մեկնաբանություն է, որը կարող է կազմված լինել
 մի քանի տողերից
 */
```

այնպես էլ մեկ տողանի մեկնաբանություններ՝

```cpp
// այս տողի մնացած մասը համարվում է մեկնաբանություն
```

որտեղ `//`–ը նշանակում է մեկնաբանության սկիզբ, իսկ ամենամոտիկ տողանցման նշանը, որը `\` նշանով (կամ նրան համարժեք `??/` նշանակմամբ) հայելիացված չէ, համարվում է մեկնաբանության ավարտ։ Ստացվում է, տվյալ տողի սահմաններում `//`–ից հետո գրված ամեն ինչ համարվում է մեկնաբանություն։

#### Տիպեր
C++ լեզվում հասանելի են հետևյալ ներկառուցված տիպերը՝
* Սիմվոլային՝ `char`, `wchar_t` (`char16_t` և `char32_t`, C++11 ստանդարտում)։
* Ամբողջաթվային նշանային՝ `signed char`, `short int`, `int`, `long int` (և `long long int`, C++11 ստանդարտում)։
* Ամբողջաթվային ոչ նշանային՝ `unsigned char`, `unsigned short int`, `unsigned int`, `unsigned long int`(և `unsigned long long int`, C++11 ստանդարտում)։
* Լողացող կետիկով՝ `float`, `double`, `long double`:
* Տրամաբանական՝ `bool`, որն կարող է ընդունել `true` և `false` արժեքներից մեկը։

Համեմատության գործողություններն վերադարձնում են `bool` տիպի արժեքներ։ `if`–ից և `while`–ից հետո դրվող փակագծերի արտահայտությունները բերվում են `bool` տիպի։

Ֆունկցիաները կարող են ընդունել արգումենտներ հղումով։ Օրինակ, `void f(int &x) {x=3;}` ֆունկցիան վերագրում է իր արգումենտին 3 արժեքը։ Ֆունկցիաները կարող են նաև արդյունքները վերադարձնել հղումով, և այդ հղումները կարող են ոչ մի կապ չունենալ ֆունկցիայի հետ։ Օրինակ, `{double &b=a[3]; b=sin(b);}` կոդը համարժեք է `a[3]=sin(a[3]);` կոդին։ Ծրագրավորման ժամանակ հղումներն ինչ–որ չափով նման են ցուցիչներին՝ հետևյալ առանձնահատկություններով․
* մինչև հղումների օգտագործումը դրանք պետք է նախօրոք ինիցիալիզացվեն,
* հղումը իր ողջ կյանքի ընթացքում ցույց է տալիս միևնույն հասցեն,
* արտահայտություններում հղումը նշանակում է այն օբյեկտը կամ այն ֆունկցիան, որին նա հղված է։ Այդ օբկյետին կամ ֆունկցիային հղման միջոցով դիմելիս անհրաժեշտ է ցուցչի հասցեի ստացում։

Գոյություն ունեն նաև այլ տարբերություններ ցուցչի և հղման օգտագործման միջև։ Ըստ գաղափարի, հղումը փոփոխականի կամ ֆունկցիայի մեկ այլ անունն է, միևնույն հասցեի մեկ այլ անվանումը։ Այն գոյություն ունի միայն ծրագրի կոդում և կոմպիլյացիայի ժամանակ փոխարինվում է իր հասցեով։ Իսկ ցուցիչը փոփոխական է, որում պահվում է հասցեն, որին դիմում են։

#### Զանազան
* `inline` սպեցիֆիկատորը թույլ է տալիս հայտարարել inline–ֆունկցիաներ։ Ֆունկցիան, որը որոշված է դասի մարմնի ներսում, լռելյայն inline է համարվում։ Ի սկզբանե inline–ֆունկցիաները մտածված էին այնպես, որ նրանք բարելավման համար լավ թեկնածուներ էին, քանի որ այն տեղերում, որտեղ կանչվում էր ֆունկցիան, կոմպիլյատորը պետք է ուղղակի տեղադրեր ֆունկցիայի մարմինը, այլ ոչ թե առանձին կատարեր ֆունկցիան և տեղադրեր արժեքը։ Իրականում կոմպիլյատորը պարտադիր չէ, որ իրականացնի inline–ֆունկցիայի մարմնի տեղադրումը այնտեղ, որտեղից կանչվում է այդ ֆունկցիան, բայց նա կարող է, ելնելով բարելավման տրված աստիճանից, այդպես վարվել ոչ inline–ֆունկցիաների հետ։ inline-ֆունկցիաների ամենամեծ առանձնահատկությունն այն է, որ այն կարող է բազմակի անգամ հայտարարվել մի քանի թարգմանման միավորներում (միևնույն ժամանակ inline-ֆունկցիան պետք է հայտարարված լինի բոլոր այն թարգմանման միավորներում, որտեղ այն օգտագործվում է), իսկ inline չհանդիսացող ֆունկցիաները կարող են հայտարարվել ծրագրում մեկից ավել անգամ։ Օրինակ՝
`inline double Sqr(double x) {return x*x;}`:
* `volatile` նկարագրիչը օգտագործվում է փոփոխականների նկարագրման ժամանակ և տեղեկացնում է կոմպիլյատորին, որ տվյալ փոփոխականի արժեքը կարող է փոխվել կոմպիլյատորի կողմից անհայտ եղանակով։ Այն փոփոխականների համար, որոնք հայտարարված են որպես `volatile`, կոմպիլյատորը չպետք է կիրառի այնպիսի բարելավման միջոցներ, որոնք փոփոխում են փոփոխականի տեղը հիշողության մեջ (օրինակ, այն ռեգիստր տեղափոխող միջոցներ) կամ ենթադրում են, որ փոփոխականի արժեքը նրա երկու վերագրման գործողությունների միջև չի փոփոխվելու։ Բազմամիջուկ համակարգերում `volatile`–ն օգնում է խուսափել հիշողության 2–րդ կարգի խոչընդոտներից։
* Եթե նկարագրված է կառուցվածք, դաս, միավորում (`union`) կամ թվարկում (`enum`), նրա անունը հանդիսանում է տիպի անուն, օրինակ՝

```cpp
struct Time {
    int hh, mm, ss;
};
Time t1, t2;
```

* Ավելացված են անվանատարածքները (namespace)։ Օրինակ, եթե գրենք՝

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

ապա ձևավոր փակագծերից դուրս T–ին, x–ին, f–ին, g–ին դիմելիս պետք է համապատասխանաբար գրել այսպես՝ Foo::T, Foo::x, Foo::f և Foo::g։ Եթե որևէ ֆայլում անհրաժեշտ է անմիջականորեն դիմել այդ անվանատարածքի անդամներին, կարելի է գրել՝

```cpp
using namespace Foo;
```

Կամ այսպես՝

```cpp
using Foo::T;
```

Անվանատարածքներն անհրաժեշտ են, որպեսզի համընկնող անուններով գլոբալ փոփոխականներ, ֆունկցիաներ և տիպեր ունեցող փաթեթների միջև անհամաձայնություններ չառաջանան։ Որպես մասնավոր դեպք կարելի է նշել անանուն անվանատարածքը՝

```cpp
namespace
{
    ...
}
```

Նրանում հայտարարված բոլոր անունները հասանելի են միայն ընթացիկ թարգմանման միավորում և ուրիշ ոչ մի տեղ։
* Ֆունկցիայի մեկ կամ մի քանի վերջին արգումենտները կարող են տրվել լռելյան։ Օրինակ, եթե ֆունկցիան նկարագրված է որպես `void f(int x, int y=5, int z=10)`, ֆունկցիայի `f(1)`, `f(1,5)` և `f(1,5,10)` կանչերը համարժեք են միմյանց։
* Ֆունկցիաների հայտարարման ժամանակ փակագծերում արգումենտների բացակայությունը նշանակում է, որ արգումենտներ չկան, այլ ոչ թե, որ դրանք անհայտ են, ինչպես C լեզվում է։ Եթե արգումենտներն անհայտ են, ապա պետք է օգտվել բազմակետերից, օրինակ, `int printf(const char* fmt, ...)`:
* Կառուցվածքի կամ դասի մեջ կարելի է նկարագրել ներդրված տիպեր, ինչպես `typedef`–ի միջոցով, այնպես էլ այլ դասերի, ինչպես նաև՝ թվարկումների նկարագրմամբ։ Դասից դուրս այդպիսի տիպերին դիմելու համար նրանց անվանը ավելացվում է կառուցվածքի կամ դասի անունը և երկու հատ երկու կետ՝

```cpp
struct S
{
    typedef int** T;
    T x;
};
S::T y;
```

* Կարող են լինել միևնույն անվանումով, բայց տարբեր տիպերով կամ արգումենտների քանակությամբ ֆունկցիաներ։ (ֆունկցիաների վերբեռնում․ վերադարձվող արժեքների տիպը չի ազդու վերբեռնման վրա)։ Օրինակ, կարող ենք գրել՝

```cpp
void Print(int x);
void Print(double x);
void Print(int x, int y);
```

* Օգտագործողի տիպերի վրա կիրառվող որոշ օպերատորների իմաստը կարելի է որոշել համապատասխան օպերատորային ֆունկցիաների հայտարարման միջոցով։ Օրինակ, այսպես՝

```cpp
struct Date {int day, month, year;};
void operator ++(struct Date& date);
```

Օպերատորային ֆունկցիաները շատ բաներում նման են սովորական (ոչ օպերատորային) ֆունկցիաներին։ Բացառությամբ `new`, `new[]`, `delete` և `delete[]` օպերատորների, չի կարելի վերասահմանել ներկառուցված տիպերի պահվածքը (ասենք, վերասահմանել int տիպի արժեքների բազմապատկման օպերատորը)։ Չի կարելի ստեղծել նոր օպերատորներ, որոնք չկան C++–ում (ասենք, `**`)։ Չի կարելի փոխել օպերատորների համար նախատեսված օպերանդների քանակը, ինչպես նաև չի կարելի փոխել օպերատորների գոյություն ունեցող առաջնահերթություններն ու ասոցիատիվությունը (ասենք, `a+b*c` արտահայտության մեջ նախ պետք է կատարվի բազմապատկման գործողությունը, և հետո միայն գումարման, ինչ տիպի էլ որ լինեն a–ն, b–ն և c–ն)։ Կարելի է վերասահմանել `[]` (մեկ պարապետրով) և `()` (ցանկացած քանակությամբ պարամետրերով) գործողություները։
* Ավելացվել են կաղապարները (`template`)։ Օրինակ, `template&lt;class T&gt; T Min(T x, T y) {return x&lt;y?x:y;}` կոդը հայտարարում է Min ֆունկցիան ցանկացած տիպի համար։ Կաղապարները կարող են տալ ոչ միայն ֆունկցիաներ, այլ նաև տիպեր։ Օրինակ, `template&lt;class T&gt; struct Array{int len; T* val;};` կոդը հայտարարում է ցանկացած տիպի արժեքների զանգված, որից հետո մենք կարող ենք գրել `Array&lt;float&gt; x;`
* Ի հավելումբ `malloc` և `free` ֆունկցիաների, ներմուծված են նաև `operator new`, `operator new[]`, `operator delete` և `operator delete[]` օպերատորային ֆունկցիաները, ինչպես նաև `new`, `new[]`, `delete` և `delete[]` օպերատորները։ Եթե T–ն ցանկացած օբյեկտային տիպ է և չի հանդիսանում զանգվածի տիպ, tt>X–ը՝ ցանկացած օբյեկտային տիպ և A–ն՝ զանգվածի տիպ, որն ունի որոշակի n քանակությամբ տարր, որոնք ունեն X տիպ, ապա
** `new T`–ն հիշողություն է հատկացնում (`operator new` ֆունկցիան կանչելու միջոցով), որն բավարար է Т տիպի մեկ արժեք տեղավորելու համար, հնարավոր է, այդ հիշողության մեջ ինիցիալիզացնում է օբյեկտը և վերադարձնում է `Т*` տիպի ցուցիչ (օրինակ, `Т* p = new T`)։
** `new X[n]`–ն ու `new A`–ն հիշողություն են հատկացնում (`operator new[]` ֆունկցիան կանչելու միջոցով), որն բավարար է X տիպի n հատ օբյեկտ տեղավորելու համար, հնարավոր է, ինիցիալիզացնում է յուրաքանչյուր օբյեկտը այդ հիշողության մեջ, և վերադարձնում է `X*` տիպի ցուցիչ (օրինակ, `X* p = new X[n]`)։
** `delete p`, հեռացնում է օբյեկտը (որը չի հանդիսանում զանգված), որին հղվում է p ցուցիչը, և ազատում է հիշողության այն հատվածը (`operator delete` ֆունկցիայի կանչման միջոցով), որն հատկացված է նրա համար new արտահայտության կողմից։
** `delete [] p`, հեռացնում է զանվածի բոլոր օբյեկտները, որին հղվում է p ցուցիչը, և ազատում է հիշողության այն հատվածը (`operator delete[]` ֆունկցիայի կանչման միջոցով), որն հատկացված է այդ զանգվածին new արտահայտության կողմից։
`delete` գործողությունը ստուգում է, արդյո՞ք իր արգումենտը զրոյական ցուցիչ չէ, հակառակ դեպքում նա ոչինչ չի անում։ non-POD դասային տիպի օբյեկտ ինիցիալիզացնելու համար new արտահայտություւնը կանչում է կառուցողին։ Դասային տիպի օբյեկտի հեռացման համար delete արտահայտությունը կանչում է ապակառուցողին (տես՝ ներքևում)։

### Օբյեկտ կողմնորոշված հնարավորություններ
C++-ը, ի տարբերություն C լեզվի, ունի օբյեկտ կողմնորոշված հնարավորություններ։ Այն ունի դասեր, որոնք ապահովում են օբյեկտ կողմնորոշված ծրագրավորման երեք կարևոր հատկությունները՝ ինկապսուլյացիան, ժառանգությունը և պոլիմորֆիզմը։

C++-ի ստանդարտում դաս (class) ասելով հասկանում են օգտագործողի կողմից ստեղծված տիպ, որն հայտարարված է `class`, `struct` կամ `union` բանալի բառերից մեկի օգնությամբ, կառույց (structure) ասելով հասկանում ենք դաս, որն հայտարարված է struct բանալի բառի օգնությամբ, և միացություն (union) ասելով հասկանում են դաս, որն հայտարարված է union բանալի բառի օգնությամբ։

#### Ֆունկցիաների նկարագրումը դասի մարմնում
Դասի մարմնում կարող ենք գրել միայն ֆունկցիայի անունը, կամ նկարագրել այն ամբողջությամբ (տես ներքևում տեղադրված `Alloc` ֆունկցիայի օրինակը։ Այս դեպքում այն համարվում է ներկառուցվող (`inline`))։

#### Հաստատուն ֆունկցիա–անդամներ
Ոչ ստատիկ ֆունկցիա-անդամները (և միայն նրանք) կարող են ունենալ `const` նկարագրիչը՝

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

Այսպիսի ֆունկցիաները չեն կարող փոփոխել դասի դաշտերը (բացի այն դաշտերից, որոնք որոշված են որպես `mutable`)։ Եթե նրանք փորձեն դա անել, կոմպիլյատորը կարտարծի սխալի մասն հաղորդագրություն։

#### Ժառանգում
C++-ում, երբ մի դաս ժառանգվում է մեկ այլ դասի կողմից, ապա վերջինս ժառանգում է իր ծնող-դասի *իրականացումը*։ Ժառանգորդ-դասը կարող է ավելացնել իր դաշտերն ու ֆունկցիաները, կամ փոխարինել հիմնական դասի ֆունկցիաները։ C++-ում թույլատրվում է բազմակի ժառանգումը։

Ժառանգորդի կառուցողը կանչում է հիմնական դասերի կառուցողներին, այնուհետև ոչ ստատիկ անդամ-տվյալների կառուցողներին, որոնք հանդիսանում են դասի օրինակներ։ Ապակառուցողը նույնը կատարում է հակառակ հերթականությամբ։

Ժառանգումը լինում է հրապարակային, պաշտպանված և փակ (այսինքն փակ տիպի)՝

Կարելի է ասել, որ ժառանգորդը հիմնական դասի ընդլայնված տարբերակն է, այսինքն, եթե հիմնական դասի ժառանգումը բաց է, այն կարող ենք օգտագործել այնտեղ, որտեղ օգտագործվում է հիմնական դասը։ Հակառակը անել հնարավոր չէ։

#### Պոլիմորֆիզմ
C++-ի տիպերի համակարգի քերականությունը պոլիմորֆ չէ (ի տարբերություն ML-ի ժառանգորդների, այդ թվում C լեզվի հիբրիդների՝ BitC, Cyclone), սակայն կան պոլիմորֆ վարքն ապահովելու մի քանի եղանակներ։ Ամենից առաջ դա ժառանգման ժամանակ դասերի մեթոդների վերբեռնումն է՝ տվյալների աբստրակցիայի ապահովման օբյեկտ կողմնորոշված ծրագրավորման համար ավանդական դարձած եղականը։ Այնուհետև պարամետրիկ պոլիմորֆիզմի (C++-ի համայնքում սովորաբար անվանվող «ընհանրացված ծրագրավորման») համար կա իրականացման երկու եղանակ։ Առաջին եղանակը ժառանգված է C-ից։ Այն հիմնված է առանց տիպի ցուցչի օգտագործման և տիպի այլ տվյալներից կախված բերման վրա։ Սա C++-ում ավանդաբար համարվում է վտանգավոր եղանակ։ Երկրորդ եղանակը կաղապարների օգտագործումն է, սակայն, ի տարբերություն պարամետրիկ պոլիմորֆիզմի սովորական իրականացումների, C++-ում տեղի է ունենում վերբեռնված մոնոմորֆ ֆունկցիաների ընտանիքի ինքնուրույն գեներացիա, որն հիմնված է պոլիմորֆ որոշչի (կաղապարի)՝ համապատասխանաբար նրա օգտագործման կոնտեքսի վրա, այսինքն ելատեքստային կոդի մակարդակի պարամետրիկ պոլիմորֆիզմը թարգմանվում է մեքենայական մակարդակի իրավիճակայինի (ad hoc), ինչի համար C++-ն ենթարդկվում է քննադատությունների։ C++-ում կա նաև վերբեռնման երրորդ եղանակ՝ օպերատորների վերբեռնումը, որը դասերի ժառանգման հետ համադրված տալիս է էլ ավելի շատ հնարավորություններ կոդի ընթերցումն հեշտացնելու համար ի շնորհիվ, այսպես կոչված, «շարահյուսական շաքարի» ներմուծման։

Տվյալների աբստրակցիան ապահովելու համար անհրաժեշտ է կապել մի քանի դասեր ժառանգման հիերարխիայի մեջ և ֆունկցիաները նշանակել միանման սպեցիֆիկատորներով։ Օրինակ՝

```cpp
class Figure
{
    ...
    void Draw() const;
    ...
};

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

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

class Window
{
    ...
    void Draw() const;
    ...
};

class SquareWindow: public Window
{
    ...
    void Draw() const;
    ...
};

class RoundWindow: public Window
{
    ...
    void Draw() const;
    ...
};
```

Այս սահմանումների կոմպիլյացման արդյունքում ձևավորվում են վեց ֆունկցիաների մարմիններ։ Կոդում դրանք օգտագործվում են միանման․ ֆունկցիայի որոշակի օրինակի ընտրությունը կատարվում է կախված այն օբյեկտի օրինակի տիպից, որի համար կանչվում է ֆունկցիան։ Ֆունկցիաների վարքի համաձայնեցվածությունը պետք է ապահովի ծրագրավորողը։

```cpp
Circle *c = new Circle(0,0,5);
Figure *f = c; // ճիշտ է․ Figure-ը Circle-ի հիմնական դասն է
c->Draw();
f->Draw(); // Ցուցիչները իրար հավասար են, սակայն f-ի և c-ի համար կկանչվեն տարբեր ֆունկցիաներ
SquareWindow *sw = new SquareWindow(0,0,5);
sw->Draw(); // օգտագործվում է նույնկերպ
f = sw; // սխալ է․ SquareWindow-ն չի մտնում Figure-ի ժառանգորդների ցանկում
```

Ինչպես երևում է, C++-ում պոլիմորֆիզմի այս տեսակի շրջանակը սահմանափակվում է ցուցակով տրված տիպերի նախագծման փուլում։ Այսպիսի պոլիմորֆիզմը լռելյան համարվում է ստատիկ, սակայն `virtual` սպեցիֆիկատորի օգտագործման ժամանակ այն վերածվում է դինամիկի՝

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

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

class Circle: public Figure
{
    ...
    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` սպեցիֆիկատորով՝

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

Մաքուր վիրտուալ ֆունկցիան սահմանում չունի և չի կարող ուղղակիորեն կանչվել։ Այսպիսի ֆունկցիայի հայտարարման նպատակն է ստեղծել ընդհանուր հիմնական դասում սիգնատուր-նախատիպ, որն չունի սեփական սահմանում, բայց թույլ է տալիս ստեղծել այդպիսի սահմանումներ ժառանգորդ-դասերում և ցուցիչի միջոցով կանչել դրանք ընդհանուր հիմնական դասին։ Ֆունկցիա-անդամը հայտարարվում է մաքուր վիրտուալ այն ժամանակ, երբ նրա սահմանումը հիմնական դասի համար իմաստ չունի։ Այսպես, վերընշված օրինակում Figure հիմնական դասի համար Draw() ֆունկցիայի սահմանումը իմաստ չունի, քանի որ «մարմիններ» ընդհանրապես չեն ստացվում և դրանք հնարավոր չէ ցուցադրել, սակայն այսպիսի ֆունկցիայի սահմանումը անհրաժեշտ է, որպեսզի կարելի լինի ժառանգորդ-դասերում նրան վերասահմանել և այդ դասերի Draw մեթոդը կանչել Figure-ի ցուցչի միջոցով։ Հետևաբար, միանգամայն տրամաբանական է հայտարարել Figure.Draw()-ն որպես մաքուր վիրտուալ ֆունկցիա-անդամ։

C++-ում մաքուր վիրոտուալ ֆունկցիայի հասկացության հետ սերտորեն կապված է «աբստրակտ դաս» հասկացությունը։ *Աբստրակտ դաս* են անվանում այն դասը, որն ունի գոնե մեկ չվերասահմանված մաքուր վիրտուալ ֆունկցիա-անդամ։ Այսպիսի դասերի օրինակների ստեղծումը թույլատրված չէ։ Աբստրակտ դասերը կարող են օգտագործվել միայն ժառանգման ճանապարհով նոր դասերի ստեղծման համար։ Եթե աբստրակտ դասի ժառանգորդ-դասում ժառանգված բոլոր մաքուր վիրտուալ ֆունկցիաները վերասահմանված չեն, ապա այդպիսի դասը նույնպես հանդիսանում է աբստրակտ դաս և նրա վրա նույնպես տարածվում են նշված բոլոր սահմանափակումները։

Աբստրակտ դասերը հաճախ օգտագործվում են որպես միջերեսներ։ Ի տարբերություն այլ լեզուների միջերեսների, C++ լեզվի աբստրակտ դասերը կարող են ունենալ ոչ վիրտուալ ֆունկցիաներ և անդամ-տվյալներ։

#### Ինկապսուլյացիա
C++-ում տեղեկատվության կազմակերպման հիմնական միջոց են համարվում *դասերը*։ Ի տարբերություն C լեզվի *կառույցների* (`struct`), որոնք կարող են կազմված լինել միայն *դաշտերից* և *դերդրվող տիպերից*, C++-ի դասը (`class`) կարող է կազմված լինել դաշտերից, *ներդրված տիպերից* և *ֆունկցիա-անդամներից* (member functions)։ C++-ում ինկապսուլյացիան իրականացվում է դասի անդամների հասանելիության մակարդակի նշման միջոցով։ Դրանք լինում են հրապարակային (բաց, `public`), պաշտպանված (`protected`) և սեփական (փակ, գաղտնի, `private`)։ C++-ում կառույցները դասերից տարբերվում են միայն նրանով, որ դրանցում անդամները և հիմնական դասերը հրապարակային են, իսկ դասերում՝ սեփական։

Հասանելիության ստուգումը կատարվում է կոմպիլյացիայի ժամանակ, դասի ոչ հասանելի անդամին դիմելու փորձը կհանգեցնի կոմպիլյացիայի սխալի։

Դասի օրինակ, որն իրականացնում է միաչափ զանգված՝

```cpp
class Array
{
    public:
        Array():
            len(0),
            val(NULL)
        {}

        Array(int _len):
            len(_len)
        {
            val = new double[_len];
        }

        Array(const Array & a);

        ~Array()
        {
            Free();
        }

        inline const double & Elem(int i) const
        {
            return val[i];
        }

        inline void ChangeElem(int i, double x)
        {
            val[i] = x;
        }

    protected:
        void Alloc(int _len)
        {
            if (len == 0)
                Free();

            len = _len;
            val = new double[len];
        }

        void Free()
        {
            delete [] val;
            len = 0;
        }

        int len;
        double * val;
};
```

Այստեղ Array դասն ունի 2 հրապարակային ֆունկցիա-անդամներ, 2 պաշտպանված դաշտեր, 3 հրապարակային կառուցողներ և հրապարակային ապակառուցող։ `inline` նկարագրիչը հուշում է կոմպիլյատորին, որ ֆունկցիան կանչելու փոխարեն անհրաժեշտ է այն ներկառուցել կանչելու վայրում, ինչի շնորհիվ հաճախ կարելի է հասնել մեծ արդյունավետության։

#### Ընկերներ

*Ֆունկցիա-ընկերները* այն ֆունկցիաներն են, որոնք չեն հանդիսանում ֆունկցիա-անդամներ, բայց, չնայած դրան, դասի պաշտպանված և փակ անդամները հասանելի են նրա համար։ Այս ֆունկցիաները դասի մարմնում պետք է հայտարարված լինեն `friend` բանալի բառով։ Օրինակ՝

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

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

Այստեղ Multiply ֆունկցիան կարող է դիմել Matrix դասի ցանկացած դաշտի կամ ֆունկցիա-անդամի։

Որպես ընկեր կարող է հայտարարվել ինչպես ամբողջ դասը, այնպես էլ դասի ֆունկցիա-անդամը։ Եթե A դասը հայտարարված է B դասում որպես ընկեր, ապա A դասի բոլոր սեփական (չժառանգված) ֆունկցիա-անդամները կարող են դիմել B դասի ցանկացած անդամի։ Օրինակ՝

```cpp
class Matrix {
    ...
    friend class Vector::getNum( Matrix & ) ;
    ...
private:
    int i;
};
...
class Vector
{
    int GetNum( Matrix & m ){ return m.i;} // դիմում Matrix դասի տվյալների փակ անդամին
};
```

Դիմման օրինակ՝

```cpp
void SomeFunction()
{
    Matrix m;
    Vector v;

    int i = Vector::GetNum( m );
}
```


Չորս կարևոր սահմանափակումներ, որոնք գործում են C++-ում ընկերական «հարաբերությունների» վրա՝
* **Ընկերությունը տարանցիկ չէ։** Եթե A-ն B-ին հայտարարում է որպես ընկեր, իսկ B-ն, իր հերթին, ընկեր է հայտարարում C-ին, ապա C-ն ինքնըստինքյան A-ի ընկերը չի դառնում։ Դա անելու համար A-ն պետք է հայտարարի C-ին որպես իր ընկեր։
* **Ընկերությունը փոխադարձ չէ։** Եթե A-ն հայտարարում է B-ին որպես ընկեր, ապա վերջինս ինքնըստինքյան չի դառնում A-ի ընկերը։ Դա անելու համար B դասում պետք է գոյություն ունենա A դասի հստակ ընկերության հայտարարում։
* **Ընկերությունը չի ժառանգվում։** Եթե A դասը հայտարարում է B դասին որպես իր ընկեր, ապա B-ի ժառանգորդները ինքնըստինքյան չեն դառնում A դասի ընկերներ։ Դա անելու համար դրանցից յուրաքանչյուրը պետք է հստակ ձևով հայտարարի A-ին որպես ընկեր։
* **Ընկերությունը չի տարածվում ժառանգորդների վրա։** Եթե A դասը հայտարարում է B-ին որպես ընկեր, ապա B-ն ինքնըստինքյան չի դառնում A-ի ժառանգորդ դասերի ընկերը։ Յուրաքանչյուր ժառանգորդ, անհրաժեշտության դեպքում, ինքնուրույն պետք է հայտարարի B-ին որպես իր ընկեր։
Ընդհանուր առմամբ, այս կանոնը կարելի է ձևակերպել այսպես․ *«Ընկերական հարաբերություն գոյություն ունի միայն այն դասերի (դասի կամ ֆունկցիայի) միջև, որոնց համար այն հստակ հայտարարված է կոդում և գործում է միայն այն ուղղությամբ, որով այն հայտարարված է»:*

Ըստ C++-ի գործող ստանդարտի, ներդրված դասը շրջապատող դասի փակ անդամների հասանելիության իրավունք չունի և չի կարող հայտարարել նրան որպես իր ընկեր (վերջինս հետևում է *ընկեր* եզրի՝ որպես դասի ոչ անդամ սահմանումից)։ C++0x ապագա ստանդարտում այս սահմանափակումները կվերացվեն։ Այս հարցում VC++, GNU C++ և Comeau C++ կոմպիլյատորների վերջին տարբերակները նույնիսկ անջատված ընդլայնումներով հետևում են նոր կանոններին, որոնք ձևակերպված են C++0x-ի վերջին սևագրություններում միայն։

#### Կոնստրուկտորներ և դեստրուկտորներ

Դասերն միշտ ունեն հատուկ ֆունկցիաներ՝ *[[Կոնստրուկտոր (ծրագրավորում)|Կոնստրուկտոր]]* և *[[դեստրուկտոր]]ներ*, որոնք կարող են հայտարարվել բացահայտ կամ անբացահայտ։

Կոնստրուկտորը կանչվում է օբյեկտի (համապատասխան տիպի) ստեղծման ժամանակ՝ այն ինիցիալիզացնելու նպատակով, իսկ Դեստրուկտորը՝ օբյեկտի վերացման համար։ Մասնավորապես, Կոնստրուկտորը կարող է կանչվել՝ դասային տիպի փոխակերպումը կատարելու համար։

Կոնստրուկտորները նշանակվում են որպես դասի անունը կրող ֆունկցիաներ (օրինակ, `Array::Array`)։ Դեստրուկտորը նույնպես կրում է դասի անունը, սակայն անունից առաջ դրվում է ~ նշանը (օրինակ, `Array::~Array`)։ Կոնստրուկտորների և Դեստրուկտորների համար չի կարելի նշել վերադարձվող արժեքի տիպը։ Դեստրուկտորը չի կարող ընդունել արգումենտներ։ Դասը կարող է ունենալ մի քանի Կոնստրուկտորներ (տարբեր պարամետրերով), այդ թվում՝ կաղապարային, սակայն միայն մեկ՝ ոչ կաղապարային Դեստրուկտոր։

Այն Կոնստրուկտորը, որը չունի պարամետրեր կամ որի պարամետրերը ունեն լռելյան արգումենտներ, անվանում են *լռելյան Կոնստրուկտոր*։ Եթե ոչ կաղապարային Կոնստրուկտորը, որի առաջին պարամետրը հղում է իր դասին (օրինակ, `Array::Array(const Array&)`), իսկ մնացած պարամետրերը (եթե այդպիսիք կան)՝ ոչ, և որը ունի լռելյան արգումենտներ, անվանում են *պատճենման Կոնստրուկտոր*։ Այն կանչվում է գոյություն ունեցող օբյեկտի պատճեն հանդիսացող նոր օբյեկտի ստեղծման ժամանակ՝

```cpp
Array a(5); // կանչվում է Array::Array(int)
Array b; // կանչվում է Array::Array()
Array c(a); // կանչվում է Array::Array(const Array&)
Array d=a; // կանչվում է Array::Array(const Array&)
b=c; // կանչվում է = օպերատորը
            // եթե այն որոշված չէ (ինչպես այս դեպքում), ապա կանչվում է կոմպիլյատորի կողմից  գեներացված վերագրման օպերատորը, որը
            // իրականացնում է հիմնական ենթաօբյեկտների պատճենում և ոչ ստատիկ անդամ-տվյալների տերնար պատճենում։
            // որպես կանոն, պատճենի Կոնստրուկտորը և վերագրման օպերատորը վերաիմաստավորվում են զույգերով
```

Եթե դասում չկա Կոնստրուկտորների հստակ հայտարարում, դասն ունի առանց պարամետրերի ոչ հաստակ հայտարարված Կոնստրուկտոր, որն կառուցում է ծնող-դասերի ենթաօբյեկտները և ինիցիալիզացնում է դասի դաշտերը՝ կանչելով դրանց լռելյան Կոնստրուկտորները։ Եթե դասում չկա հստակ հայտարարված պատճենող Կոնստրուկտոր, ապա դասն ունի ոչ հստակ հայտարարված պատճենող Կոնստրուկտոր, որն կատարում է աղբյուր հանդիսացող օբյեկտի բոլոր հայտարարված դաշտերի ուղիղ պատճենում համապատասխանաբար ընդունող օբյեկտի դաշտեր համապատասխան պատճենող Կոնստրուկտորների օգնությամբ։ Եթե դասում չկա հստակ հայտարարված Դեստրուկտոր, ապա դասըն ունի սեփական ոչ հստակ հայտարարված Դեստրուկտորը։

C++-ում Կոնստրուկտորները չեն կարող հայտարարվել վիրտուալ, իսկ Դեստրուկտորները՝ կարող են, և սովորաբար այդպես էլ հայտարարվում են, որպեսզի ապահովվի հղումով կամ ցուցիչով հասանելի օբյեկտի ճիշտ ոչնչացումը՝ անկախ հղման կամ ցուցչի տիպից։

#### Օպերատորների գերբեռնում
Ֆունկցիա-անդամները կարող են օպերատորներ լինել՝

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

Այնուհետև

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


## Ստանդարտ գրադարան
### Ընդհանուր կառուցվածք
C++-ի ստանդարտ գրադարանը ներառում է որոշակի միջոցների հավաքածու, որոնք պետք է հասանելի լինեն լեզվի ցանկացած իրականացման մեջ, որպեսզի ծրագրավորողներին ապահովեն լեզվի ընձեռած հնարավորությունների հարմարավետ օգտագործումը և ստեղծեն այն հիմքը, որն անհրաժեշտ է ինչպես ամենալայն սպեկտրի կիրառական հավելվածների, այնպես էլ մասնագիտացված գրադարանների մշակման համար։ С++-ի ստանդարտ գրադարանը ներառում է C լեզվի ստանդարտ գրադարանի մի մասը։ C++-ի ստանդարտը նորմատիվ հղում է պարունակում C-ի 1990 թվականի ստանդարտին և ինքնուրույն չի սահմանում ստանդարտ գրադարանի այն ֆունկցիաները, որոնք վերցված են C-ի ստանդարտ գրադարանից։

C++ լեզվի ստանդարտ գրադարանի հնարավորությունների հասանելիությունը ապահովվում է ծրագրում համապատասխան ստանդարտ գլխագիր ֆայլերի միացմամբ (`#include` դիրեկտիվի օգնությամբ)։ C++11 ստանդարտում սահմանված ընդամենը 79 այդպիսի ֆայլ։ Ստանդարտ գրադարանի միջոցները հայտարարված են որպես `std` անվանատարածք մտնող։ Այն գլխագիր ֆայլերը, որոնց անունները համապատասխանում են «cX» կաղապարին, որտեղ X-ը՝ C լեզվի ստանդարտ գրադարանի գլխագիր ֆայլի անվանումն է՝ առանց ընդլայնման (cstdlib, cstring, cstdio և այլն), պարունակում են սահմանումներ, որոնք համապատասխանում են C լեզվի ստանդարտ գրադարանի տվյալ հատվածին։ Միևնույն ժամանակ ծրագրավորողը կարող է օգտվել այնպիսի գլխագիր ֆայլերից, որոնց անվանումը համապատասխանում է «cX.h» կաղապարին (ավելացված է C-ի գլխագիր ֆայլերի «.h» ստանդարտ ընդլայնումը), որոնց մեջ նույն միջոցները սահմանված են որպես գլոբալ անվանատարածքին վերաբերող։

Ստանդարտ գրադարանի հետևյալ ֆունկցիաների օգտագործման համար որևէ գլխագիր ֆայլեր միացնել հակավոր չէ․

```cpp
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new[](std::size_t) throw(std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
```


### Պարունակություն
Ստանդարտ գրադարանը ներառում է հետևյալ բաժինները՝
* *Լեզվի աջակցությունը*։ Ներառում է ծրագրի աշխատանքի համար անհրաժեշտ միջոցներ, ինչպես նաև իրականացման առանձնահատկությունների մասին մանրամասները։ Հիշողության հատկացումը, RTTI-ն, հիմնական բացառությունները, տվյալների թվային տիպերի համար արժեքների սահմանները, միջավայրի հետ փոխազդեցության հիմնական միջոցները, ինչպիսիք են համակարգի ժամը, UNIX-ի ազդանշանների մշակումը, ծրագրի ավարտումը։
* *Ստանդարտ կոնտեյներները*։ Ստանդարտ գրադարանի մեջ են մտնում հետևյալ կոնտեյներների համար կաղապարները՝ միաչափ զանգվածները, ցանկերը, մեկ- և երկուղղված հերթերը, սթեքերը, ասոցիացվող զանգվածները, բազմությունները, առաջնահերթություններով հերթերը։
* *Հիմնական օժանդակ ծրագրերը*։ Այս բաժնի մեջ են մտնում ստանդարտ գրադարանում կիրառվող հիմնական տարրերի նկարագրումը, հիշողության հատկացնողները և С լեզվի ոճով ժամանակի աջակցությունը։
* *Իտերատորները*։ Ապահովում է իտերատորների կաղապարները, որոնց օգնությամբ ստանդարտ գրադարանում իրականացվում է կոնտեյներների տարրերին տվյալների մշակման ալգորիթմների խմբավորված կիրառման ստանդարտ մեխանիզմը։
* *Ալգորիթմները*։ Մշակման գործողությունների նկարագրման կաղապարներ, որոնք ստանդարտ գրադարանի մեխանիզմների օգնությամբ կարող են կիրառվել տարրերի ցանկացած հաջորդականությամբ վրա, այդ թվում կոնտեյներների տարրերի։ Այս բաժնի մեջ են մտնում նաև C լեզվի ստանդարտ գրադարանի bsearch() և qsort() ֆունկցիաների նկարագրությունները։
* *Տողերը*։ C++-ի ոճով տողերի կաղապարներ։ Այս բաժնի մեջ են մտնում նաև C լեզվի ոճով տողերի և նշանների հետ աշխատանքի գրադարանի մի մասը։
* *Մուտքը և ելքը*։ Կաղապարներ և օգնող դասեր ընդհանուր տեսքի մուտքի ելքի հոսքի, տողային մուտքի-ելքի հոսքի, մանիպուլյատորների (C++-ի ոճով հոսքային մուտքի-ելքի ձևաչափի կառավարման միջոցներ) համար։
* *Տեղայնացումը*։ Սահմանումներ, որոնք օգտագործվում են С++-ի և C-ի ոճով ներկայացման ազգային առանձնահատկությունների և ձևաչափերի աջակցման համար։
* *Դիագնոստիկան*։ Բացառությունների շարքերի և կատարման ժամանակ պնդումների ստուգման մեխանիզմների (assert) սահմանումներ։ Սխալների մշակման աջակցում C-ի ոճով։
* *Թվերը*։ Կոմպլեքս թվերի, մաթեմատիկական վեկտորների աշխատանքի համար սահմանումներ, ընդհանուր մաթեմատիկական ֆունկցիաների աջակցում, պատահական թվերի գեներատոր։

Կոնտեյներները, տողերը, ալգորիթմները, իտերատորները և հիմնական օժանդակ ծրագրերը, բացառությամբ C-ի գրադարանից վերցվածների, միասին անվանում են STL (Stanard Template Library, ստանդարտ կաղապարային գրադարան)։ Ի սկզբանե այս գրադարանը առանձին է եղել և նրա հապավումը այլ ձևով էր ընդլայնվում, սակայն հետագայում այն մտավ C++-ի ստանդարտ գրադարանի մեջ՝ որպես նրա անբաժաների մաս։ Անվան մեջ արտացոլված է այն, որ ընդհանուր տեսքի միջոցների (կոնտեյներների, տողերի, ալգորիթմների) իրականացման համար օգտագործված են ընդհանրացված ծրագրավորման մեխանիզմները (C++-ի կաղապարները՝ template)։ Ստրաուստրուպի աշխատանքներում մանրամասն նկարագրված են այն պատճառները, որոնց համար հենց այդպիսի ընտրություն է կատարվել։ Հիմնական պատճառը ընտրված լուծման մեծ ունիվերսալությունն է (կաղապարային կոնտեյներները, ի տարբերություն օբյեկտայինների, կարող են հեշտությամբ օգտագործվել ոչ օբյեկտային տիպերի համար և չեն պահանջում այդ տարրերի ընդհանուր նախնիի առկայությունը) և նրա տեխնիկական արդյունավետությունը (որպես կանոն, կաղապարային կոնտեյների գործողությունները չեն պահանջում վիրտուալ ֆունկցիաների կանչեր և կարող են հեշտությամբ ներկառուցվել (inline), ինչն արդյունքում տալիս է այնպիսի արդյունավետ կոդ, ինչպիսին կլիներ ձեռքով կոդավորման ժամանակ)։

### Իրականացումներ
STL-ը, մինչև C++-ի ստանդարտին միանալը, իրենից ներկայացրել է երկրորդական մշակում, սկզբում HP ընկերության, այնուհետև՝ SGI: Լեզվի ստանդարտը այն «STL» չի անվանում, քանի որ այդ գրադարանը դարձել է լեզվի անբաժանելի մասը, սակայն շատերը մինչև այսօր էլ օգտագործում են այդ անվանումը, որպեսզի այն տարբերեն ստանդարտ գրադարանի մնացած մասին (մուտքի-ելքի հոսքերը (iostream), C-ի ենթաբաժինը և այլն)։

STLport անվանումով նախագիծը, որն հիմնված է SGI STL-ի վրա, իրականացնում է STL-ի, IOstream-ի և տողային դասերի մշտական թարմացումը։ Որոշ այլ նախագծեր նույնպես զբաղվում են ստանդարտ գրադարանի մասնավոր կիրառումների մշակմամբ։

## C լեզվի հետ համատեղելիություն
### Նոր հնարավորություններ
C++ լեզվի նոր հնարավորությունները, որոնք բացակայում էին C լեզվում՝
* օբյեկտ կողմնորոշված ծրագրավորման աջակցում,
* ընդհանրացված ծրագրավորման աջակցություն կաղապարների միջոցով,
* լրացուցիչ տվյալների տիպեր,
* բացառություններ,
* անվանատարածքներ,
* ներկառուցվող ֆունկցիաներ,
* օպերատորների վերբեռնում,
* ֆունկցիաների անունների վերբեռնում,
* հղումներ և ազատ տեղակայված հիշողության կառավարման օպերատորներ,
* ստանդարտ գրադարանի լրացումներ։

C++-ի նոր հնարավորությունները ներառում են արտահայտությունների տեսքով հայտարարությունները, ֆունկցիաների տեսքով տիպերի փոխարկումները, `new` և `delete` օպերատորները, `bool` տիպը, հղումները, հաստատունության ընհանրացված հասկացությունը, inline-ֆունկցիաները, լռելյան արգումենտները, վերասահմանումները, անվանատարածքները, դասերը (այդ թվում և դասերի հետ կապված բոլոր հնարավորությունները, ինչպիսիք են ժառանգումը, ֆունկցիա-անդամները, վիրտուալ ֆունկցիաները, աբստրակտ ֆունկցիաները և կառուցողները), օպերատորների վերասահմանումները, կաղապարները, `::` օպերատորը, բացառությունների մշակումը, դինամիկ նույնականացումը և այլ հնարավորություններ։ C++ լեզուն շատ դեպքերում նաև ավելի խիստ է վերաբերվում տիպերի ստուգմանը, քան C-ն։

C++-ում նոր մեկնաբանություններ են հայտնվել երկու գծերի տեսքով (`//`), որոնք եղել են C-ի նախորդի մոտ՝ BCPL լեզվում։

C++ լեզվի որոշ առանձնահատկություններ ավելի ուշ տեղափոխվել են C լեզու, օրինակ, `const` և `inline` բանալի բառերը, `for` ցիկլերում հայտարարումը և C++-ի ոճով մեկնաբանությունները (`//`)։ Ավելի C-ի հետագա իրականացումներում ներկայացված էին նաև այնպիսի հնարավորություններ, որոնք չկան C++-ում, օրինակ `va_arg` մակրոսները և զանգված-պարամետրերի հետ բարելավված աշխատանքը։

### C++-ը իր մեջ չի ներառում C-ն
Չնայած նրան, որ C լեզվով գրված կոդի մեծ մասը կաշխատի նաև C++-ում, վերջինս իր մեջ չի ներառում C լեզուն։ Գոյություն ունի նաև C լեզվի համար աշխատող այնպիսի կոդ, որը չի աշխատում C++-ում։ Սա է C++-ի տարբերությունը Objective C-ից՝ C լեզվի օբյեկտ կողմնորոշված ծրագրավորման ևս մեկ բարելավում, որն հենց ամբողջությամբ ներառում է C լեզուն։

Գոյություն ունեն նաև ուրիշ տարբերություններ։ Օրինակ, C++-ը չի թույլատրում կանչել `main()` ֆունկցիան ծրագրի ներսում, այն ժամանակ, երբ C-ում այդ գործողությունը թույլատրվում է։ Բացի այդ, C++-ն որոշ հարցերում ավելի խիստ է․ օրինակ, այն չի թույլատրում դեռևս չհայտարարված ֆունկցիաների օգատգործումը։

Ավելին, կոդը, որը ճիշտ է երկու լեզուների համար էլ, կարող է տալ տարբեր արդյունքներ, կախված, թե որ լեզվի կոմպիլյատորով է այն կոմպիլյացված։ Օրինակ, հարթակների մեծամասնությունում ստորև բերված ծրագիրը տպում է «C», եթե կոմպիլյացվում է C-ի կոմպիլյատորով, և «C++»՝ C++-ի կոմպիլյատորով։ Այսպես տեղի է ունենում այն պատճառով, որ C-ում սիմվոլային հաստատունները (օրինակ, `'a'`-ն) ունեն `int` տիպ, իսկ C++-ում՝ `char` տիպ, իսկ այդ տիպերի չափսերը սովորաբար տարբերվում են միմյանցից։

```cpp
#include <stdio.h>

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


## Ծրագրերի օրինակներ
Ստորև ներկայացված են C++ ծրագրավորման լեզվով գրված ծրագրերի կոդեր՝ իրենց բացատրություններով։

### Օրինակ № 1
Սա մի ծրագրի օրինակ է, որը ոչինչ չի անում։ Այն սկսում է կատարվել և անմիջապես դադարեցնում է աշխատանքը։ Այն կազմված է հիմնական հոսքից՝ `main()` ֆունկցիայից, որն հանդիսանում է C++ ծրագրի կատարման սկզբնական կետ։

```cpp
int main()
{
    return 0;
}
```

C++–ի ստանդարտը պահանջում է, որ `main()` ֆունկցիան վերադարձնի `int` տիպ։ Այն ծրագիրը, որի `main()` ֆունկցիան վերադարձնում է այլ տիպի արժեք, չի համապատասխանում C++–ի ստանդարտին։

Ստանդարտը չի ասում, թե ինչ է իրականում նշանակում `main()` ֆունկցիայի վերադարձվող արժեք ասվածը։ Ավանդաբար համարում են, որ այն վերադարձնում է ծրագրի կոդը։ Ստանդարտն երաշխավորում է, որ եթե `main()` ֆունկցիան վերադարձնում է 0 արժեք, ապա ծրագրի կատարումն ավարտվել է հաջողությամբ։

C++–ով գրված ծրագրի աշխատանքի սխալով ավարտումը ավանդաբար նշանակում է ոչ զրոյական արժեքի վերադարձ։

### Օրինակ № 2
Այս ծրագիրը նույնպես ոչինչ չի անում, բայց ավելի հակիրճ է։

```cpp
int main(){}
```

C++–ում (ինչպես և C–ում), եթե ծրագրի կատարումը հասնում է `main()` ֆունկցիայի ավարտին, ապա այն համարժեք է `return 0;`–ին։ Դա ճիշտ է միայն `main()` ֆունկցիայի համար։

### Օրինակ № 3
Սա Hello, world! ծրագրի օրինակ է, որն արտարծում է հաղորդագրություն՝ օգտագործելով ստանդարտ գրադարանը, և ավարտում է աշխատանքը։

```cpp
// սա միացնում է iostream գլխագիր ֆայլը
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello, world!" << endl; // endl–ի փոխարեն կարելի է գրել նաև "...\n"
    return 0;
}
```


### Օրինակ № 4
Ժամանակակից C++ –ը թույլ է տալիս պարզ եղանակով լուծել ավելի բարդ խնդիրներ։ Այս օրինակը, ամեն ինչից զատ, ցուցադրում է կաղապարների ստանդարտ գրադարանի (STL) կոնտեյներների օգտագործումը։

```cpp
#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["Ani"].push_back("scarf");
   items["Davit"].push_back("tickets");
   items["Ani"].push_back("puppy");

   // Կրկնում ենք բոլոր օբյեկտներն կոնտեյներում
   for_each(items.begin(), items.end(), display_item_count);
}
```

Այս օրինակում պարզության համար օգտագործվում է անվանատարածքի օգտագործման դիրեկտիվ։ Իրական ծրագրում հաճախ խորհուրդ է տրվում օգտագործել հայտարարություններ, որոնք դիրեկտիվներից ավելի կոկիկ են՝

```cpp
#include <vector>

int main()
{
    using std::vector;

    vector<int> my_vector;
}
```

Այստեղ դիրեկտիվը տեղադրված է ֆունկցիայի հատվածում, ինչը նվազեցնում է անունների միջև հնարավոր անհամաձայնությունները (ինչն էլ հենց պատճառ է հանդիսացել ծրագրավորման լեզուներում անվանատարածքների ներմուծման)։ Այնպիսի հայտարարությունների օգտագործումը, որոնք միավորում են տարբեր անվանատարածքներ մեկի մեջ, հակասում է անվանատարածքների օգտագործման հասկացությանը։

### Օրինակ № 5
boost հանրահայտ գրադարանները լեզվի ստանդարտ միջոցների հետ համադրությամբ թույլ են տալիս շատ հակիրճ և ընկալելի գրել կոդը։ Ստորև բերված օրինակում հաշվվում է կենտ թվերի և իրենց քառակուսիների վեկտորների սկալյար արտադրյալը։ Կոդում արժեքները վեկտորները տրված են ծույլ STL–անման հաջորդականություններով։

```cpp
#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++-ի հիմունքները

## Ծանոթագրություններ

## Արտաքին հղումներ
* C++ Ծրագրավորման Արվեստ
* C++ դասընթացներ
* Introduction to C++
* Apache C++ Standard Library Documentation
* C++ FAQ Lite by Marshall Cline

Կատեգորիա:ISO ստանդարտի ծրագրավորման լեզուներ
Կատեգորիա:ISO ստանդարտներ
Կատեգորիա:Օբյեկտ կողմնորոշված ծրագրավորման լեզուներ