Operátorok (C++)

A legtöbb programozási nyelv tartalmaz operátorokat, ezek speciális függvények, precedenciával, sokszor speciális(infix, postfix) jelölésmóddal, valamint a hagyományos függvényforma nélkül. A C++ átvette a C összes operátorát, valamint bevezetett újakat is, valamint néhánynak a szemantikáját is megváltoztatta.

Az operátorokat csoportosíthatjuk létrehozásuk célja szerint, így vannak aritmetikai, összehasonlító, bitszintű és egyéb operátorok.

Operátorok fordítása

A C++ fordítóban minden operátort hagyományos függvényalakra hoz a fordításkor előtt, így például az a+b alakból a.operator+(b) vagy operator+(a,b) lesz, attól függően, hogy tag vagy globális függvényként van deklarálva.

Az operátorok másik speciális tulajdonsága a precedenciájuk valamint az (bal vagy jobb) asszociativitásuk, ez határozza meg a kifejezések kiértékelési sorrendjét valamint az implicit zárójelezés irányát.

Specialitások

Konverziós operátorok

A C++ a hagyományos (type)arg alakú, C-stílusú konverzión túl alkalmaz három, ennél speciálisabb konverziós operátort, amivel egyértelműbbé tehetjük, hogy mit szeretnénk, és a fordító szólhat, ha az nem lehetséges, valamint hosszuk következtében kiugranak a kódból, könnyebbé téve a konverziók megtalálását, amelyek a pointerek után elsőszámú hibaforrásnak tekinthetők.

Alakjuk: operátornév<új-típus>(objektum);

static_cast

Konverzió egymásba konvertálható típusok között, fordítási hibát okoz, ha nem konvertálható oda-vissza a két típus.

reinterpret_cast

Erős átalakítás, gyakorlatilag tetszőleges típusok közötti átalakítást enged, veszélyes, kerülendő.

dynamic_cast

Pointerek és referenciák közötti futásidejű átalakítás, amely downcastra használható, azaz bázispointerből származtatott osztályra mutatót ad vissza. A konverzió mutatók esetén nullpointerrel tér vissza, referenciáknál (egyéb opciók híján) bad_cast kivételt dob, ha nem lehetséges az átalakítás, azaz a mutatott objektum típusa nem az elvárt.

const_cast

A konverzió leveszi a const vagy a volatile jelzőt egy változóról, szintén veszélyes lehet.

Tagként deklarált operátorok

A C++ lehetővé teszi konstruktorszerű szintaxissal konverziós operátorok használatát felhasználói típusoknál is.

Ekkor minden adott típust kívánó környezetben a normális konverziós szabályok szerint képesek konvertálódni. Az egyparaméterű (nem-explicit) konstruktorok és ezek az operátorok könnyen többértelműséget okozhatnak, mivel mindkettő képes implicit konverzióként viselkedni.

struct A{  operator int()  { return 4; }};struct B{  operator A()  { return A(); }};int main(){  int aint = A();  //aint értéke ekkor 4  A b = B();       //B() konvertálódik A-vá  int bint = b;    //bint is négy}

Operátorok túlterhelése

A közönséges függvényekhez hasonlóan a legtöbb operátort is túl lehet terhelni, amely a felhasználói típusok kényelmesebb használatát teszi lehetővé(jellemző például az <<(eltoló) operátor túlterhelése, melyet a kimeneti folyamok használnak kimenetként). Értékadó(=, += stb.), &(címe) operátort csak tagfüggvényként lehet megírni, minden mást érdemesebb globálisként deklarálni, ha lehet(ha nem kell hozzáférniük a tagokhoz).

struct Complex{ //Barátfüggvény deklarációja, hogy hozzáférjen a tagokhoz friend std::ostream& operator<<(std::ostream& stream, const Complex& z); //Konstruktor, taginicializációs listával Complex(double a, double b): re(a), im(b) { } Complex& operator+=(const Complex& rhs)         //hozzáadó operátor tagfüggvény... {re += rhs.re; im += rhs.im; return *this;} private:  double re, im;};Complex operator+(const Complex& lhs, const Complex& rhs)  //összeadó operátor viszont globális{return Complex(lhs) += rhs;}//az ostream definíciójához nem férünk hozzá, de//operator<<(ostream&, const complex&)-t definiálhatunkstd::ostream& operator<<(std::ostream& stream, const Complex& z){ return (stream << '(' << z.re << ", " << z.im << ')');}//Ezután az operátort egyszerűen használhatjuk:Complex c(1.0, 4.6);std::cout << c; //A kimeneten megjelenik: (1.0, 4.6)

Összefoglaló táblázat

PrecedenciaOperátorRövid leírásAsszociativitásJelölésCsak C++-banTúlterhelhető
1::Hatókör-feloldásnincsa::b, ::bIgenNem
2()
[]
->
.
++
--
Csoportosítás
Tömb-elérés
Mutatón keresztüli tag-elérés
Objektumon keresztüli tag-elérés
Posztfix növelés
Posztfix csökkentés
Bal(a)
a[]
ptr->b()
a.b()
a++
a--
NemNem
Igen
Igen
Nem
Igen
Igen
3!
~
++
--
-
+
*
&
(típus)
sizeof
Logikai tagadás
Bitenkénti negálás
Prefix növelés
Prefix csökkentés
Előjel -
Előjel +
Dereferálás
Objektum címe
Konverzió típusra
Méret
Jobb!a
~a
++a
--a
-a
+a
*ptr
&a
(b)a
sizeof(a)
NemIgen
Igen
Igen
Igen
Igen
Igen
Igen
Igen
Igen
Nem
4->*
.*
Tagkiválasztás mutatón/objektumonBala->*b()
a.*b()
IgenIgen
Nem
5*
/
 %
Szorzás
Osztás
Maradékszámítás
BalInfixNemIgen
6+
-
Összeadás
Kivonás
BalInfixNemIgen
7<<
>>
Bitenkénti eltolás balra
Bitenkénti eltolás jobbra
BalInfixNemIgen
8<
<=
>
>=
Kisebb
Kisebb-egyenlő
Nagyobb
Nagyobb-egyenlő
BalInfixNemIgen
9==
 !=
Egyenlő
Nemegyenlő
BalInfixNemIgen
10&Bitenkénti ÉSBalInfixNemIgen
11^Bitenkénti kizáró VAGYBalInfixNemIgen
12|Bitenkénti megengedő VAGYBalInfixNemIgen
13&&Logikai ÉSBalInfixNemIgen
14||Logikai(megengedő) VAGYBalInfixNemIgen
15? :if-then-else operátorJobblogikai-kif ? kifejezés : kifejezésNemNem
16=
+=
-=
*=
/=
 %=
&=
^=
|=
<<=
>>=
Értékadás
Összeadás és értékadás
Kivonás és értékadás
Szorzás és értékadás
Osztás és értékadás
Maradékképzés és értékadás
Bitenkénti ÉS és értékadás
Bitenkénti kizáró VAGY és értékadás
Bitenkénti megengedő VAGY és értékadás
Eltolás balra és értékadás
Eltolás jobbra és értékadás
JobbInfixNemIgen
17,Szekvencia operátorBala, bNemIgen