Operátorok (C++)
Ez a szócikk nem tünteti fel a független forrásokat, amelyeket felhasználtak a készítése során. Emiatt nem tudjuk közvetlenül ellenőrizni, hogy a szócikkben szereplő állítások helytállóak-e. Segíts megbízható forrásokat találni az állításokhoz! Lásd még: A Wikipédia nem az első közlés helye. |
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
[szerkesztés]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
[szerkesztés]Konverziós operátorok
[szerkesztés]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
[szerkesztés]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
[szerkesztés]Erős átalakítás, gyakorlatilag tetszőleges típusok közötti átalakítást enged, veszélyes, kerülendő.
dynamic_cast
[szerkesztés]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
[szerkesztés]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
[szerkesztés]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
[szerkesztés]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
[szerkesztés]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 |