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álhatunk std::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
+ Precedencia Operátor Rövid leírás Asszociativitás Jelölés Csak C++-ban Túlterhelhető 1 :: Hatókör-feloldás nincs a::b, ::b Igen Nem 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-- Nem Nem 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) Nem Igen Igen Igen Igen Igen Igen Igen Igen Igen Nem 4 ->* .* Tagkiválasztás mutatón/objektumon Bal a->*b() a.*b() Igen Igen Nem 5 * / % Szorzás Osztás Maradékszámítás Bal Infix Nem Igen 6 + - Összeadás Kivonás Bal Infix Nem Igen 7 << >> Bitenkénti eltolás balra Bitenkénti eltolás jobbra Bal Infix Nem Igen 8 < <= > >= Kisebb Kisebb-egyenlő Nagyobb Nagyobb-egyenlő Bal Infix Nem Igen 9 == != Egyenlő Nemegyenlő Bal Infix Nem Igen 10 & Bitenkénti ÉS Bal Infix Nem Igen 11 ^ Bitenkénti kizáró VAGY Bal Infix Nem Igen 12 | Bitenkénti megengedő VAGY Bal Infix Nem Igen 13 && Logikai ÉS Bal Infix Nem Igen 14 || Logikai(megengedő) VAGY Bal Infix Nem Igen 15 ? : if-then-else operátor Jobb logikai-kif ? kifejezés : kifejezés Nem Nem 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 Jobb Infix Nem Igen 17 , Szekvencia operátor Bal a, b Nem Igen
Kategória:Informatika