|
|
int
) li se aplică operatorul de adunare și apoi operatorul de atribuire. Pentru un tip de dată aritmetic fundamental, sensul acestor operații este evident și neambiguu, dar se poate întâmpla ca pentru o anumită clasă sa nu fie așa. De exemplu:
|
|
b
și c
. De fapt, doar această secvență generează eroare la compilare, pentru tipul de dată clasa_mea
nu s-a definit operația de adunare. Totuși, C++ permite celor mai multor operatori să fie supraîncărcați, astfel încât comportamentul lor să poată fi definit pentru orice alt tip, inclusiv clase. Iată o listă a tuturor operatorilor care pot fi supraîncărcați:Operatori ce pot fi supraîncărcați |
---|
|
operator
care sunt funcții obișnuite dar cu nume speciale: numele lor încep cu cuvântul cheie operator
urmat de simbolul operatorului ce trebuie supraîncărcat. Sintaxa este:tip_dată operator simbol (parameteri) { /*... corp ...*/ }
x
și y
. Operația de adunare a doi vectori cartezieni este definită prin adunarea celor douâ coordonate x
, respectiv a celor două coordonate y
. De exemplu, prin adunarea vectorilor cartezieni (3,1)
și (1,2)
se obține rezultatul (3+1,1+2) = (4,3)
. Acesta se poate implementa în C++ cu următoarea secvență:
|
|
4,3 |
CVector
par să creeze confuzie, să ne gândim că unele dintre ele se referă la numele clasei (adica tipul de dată) CVector
, iar altele sunt funcții cu acest nume (reprezentând constructori, care trebuie să aibă același nume cu clasă). De exemplu:
|
|
operator+
a clasei CVector
supraîncarcă operatorul de adunare (+
) pentru acel tip de dată. Odată declarată, această funcție poate fi apelată fie implicit folosind operatorul, fie explicit folosind numele funcției:
|
|
|
|
operator+
prin scădere sau cea care supraîncarcă operator==
prin completarea cu zerouri a obiectului, sunt perfect valide, deși folosirea unei asemenea clasei reprezintă într-adevăr o sfidare a sensului firesc.operator+
este operandul din partea dreaptă a operatorului. La fel se întâmplă pentru toți operatorii binari (cei care au un operand în stânga și unul în dreapta lor). Dar există operatori cu forme diverse. Dăm în continuare un tabel cu sinteza parametrilor necesari pentru fiecare dintre operatorii ce pot fi supraîncărcați (atenție, @
ar trebui înlocuit cu un operator din fiecare caz):Expresie | Operator | Funcție membru | Funcție care nu e membru |
---|---|---|---|
@a | + - * & ! ~ ++ -- | A::operator@() | operator@(A) |
a@ | ++ -- | A::operator@(int) | operator@(A,int) |
a@b | + - * / % ^ & | < > == != <= >= << >> && || , | A::operator@(B) | operator@(A,B) |
a@b | = += -= *= /= %= ^= &= |= <<= >>= [] | A::operator@(B) | - |
a(b,c...) | () | A::operator()(B,C...) | - |
a->b | -> | A::operator->() | - |
(TYPE) a | TYPE | A::operator TYPE() | - |
a
este un obiect al clasei A
, b
este un obiect al clasei B
și c
este un obiect al clasei C
. TYPE
este orice tip de dată (pe care operatorii îl supraîncarcă prin conversia la TYPE
).operator+
. Dar unii operatori pot fi supraîncărcați și prin funcții care nu sunt membri; în acest caz, funcția operator are ca prim argument un obiect al clasei respective.
|
|
4,3 |
this
reprezintă un pointer câtre obiectul al cărei funcție membru este executată. Se folosește în interiorul unei funcții membru a unei clase pentru a se face referirea chiar la obiectul respectiv.
|
|
da, &a este b |
operator=
care returnează obiecte prin referință. Revenind la exemplul vectorului cartezian de mai înainte, funcția sa operator=
s-ar fi putut defini astfel:
|
|
operator=
.
|
|
7 6 |
|
|
|
|
n
din clasa Tantalau
distribuită tuturor obiectelor acestei clase.this
.const
:
|
|
const
pentru tot ceea ce le apelează din afara clasei. Să observăm, totuși, apelul constructorului și permiterea inițializării și modificării datelor membru:
|
|
10 |
const
pot fi apelate numai dacă ele însele sunt marcate ca membri const
; în exemplul de mai sus, membrul get
(care nu este marcat cu const
) nu poate fi apelat din foo
. Pentru a marca un membru ca fiind const
, cuvântul cheie const
ar trebui să urmeze prototipului funcției, după închiderea parantezelor cu parametri:
|
|
const
poate fi folosit pentru a califica tipul returnat de o funcție membru. Acest const
nu este același cu cel care precizează că un membru este const
. Cele două sunt independente și se poziționează în locuri diferite în prototipul funcției:
|
|
const
nu pot modifica date membru nestaticeși nici nu pot apela alte funcții membru care nu sunt const
. În esență, membrilor const
nu li se permite să modifice starea unui obiect.const
sunt restricționate la accesarea numai a membrilor marcați cu const
, dar obiectele non-const
nu sunt restricționate și pot accesa atât membri const
cât și non-const
.const
, deci nu merită efortul de a declara const toți membrii care să nu modifice obiectul, însă obiectele const sunt chiar foarte întâlnite. Majoritatea funcțiilor care au ca parametri clase o fac prin referințe const
, deci aceste funcții pot să acceseze doar membrii const
:
|
|
10 |
get
nu ar fi fost marcat ca membru const
, nu ar fi fost posibil apelul lui arg.get()
din funcția print
, deoarece obiectele const
au acces numai la funcțiile membru const
.const
iar cealaltă nu; în acest caz, versiunea const
este apelată numai când obiectul însuși este const, iar cea non-const
este apelată când obiectul este non-const
.
|
|
15 20 |
|
|
int
cu valorile 115, respectiv 36, am fi scris:
|
|
|
|
template <...>
:
|
|
100 |
getmax
:
|
|
T
-uri? Sunt trei T
-uri în această declarație: primul este parametrul șablonului. Al doilea T
se referă la tipul de dată returnat de funcție. Iar ce de-al treilea T
(cel dintre parantezele unghiulare) este și el necesar: el precizează faptul că parametrul acestui șablon de funcție este și parametrul șablonului de clasă.containerul_meu
, care poate stoca un element de orice tip si care are doar o funcție membru numită marire
, care îi crește valoarea. Dar credem că este mai potrivit ca atunci când memorează un element de tip char
ar fi mult mai convenabil să avem o implementare cu o funcție majuscula
, așa încât decidem să declarăm o specializare a unui șablon de clasă pentru acel tip de dată:
|
|
8 J |
|
|
template<>
, incluzând și o listă vidă de parametri. Și facem acest lucru pentru că sunt recunoscute toate tipurile de dată și nu sunt necesare argumente pentru șablon în această specializare, dar este o specializare a unui șablon de clasă, iar acest fapt se semnalează astfel.<char>
de după numele șablonului de clasă. Chiar acest parametru de specializare identifică tipul de dată pentru care se face specializarea șablonului (char
). Să observăm diferența dintre șablonul generic de clasă și specializare:
|
|
Previous: Clase (I) | Index | Next: Membri speciali |