Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Overloading


A C++ nyelvben például a + és - operátoroknak több független funkciója van: aritmetikai műveleteket végez
egész számokkal, valós számokkal és mutatókkal. Hogy hogyan végezi a műveletet,
az a kontextustól függ, azaz hogy milyen adattípussal van használva. Minden
adattípusnál másképp dolgozik, azaz másképp van definiálva a művelet. Ezek a
definíciók vagy átdefiniálások úgymond túlterhelik az operátort (overloading).
Saját adattípussal is túl lehet terhelni az operátorokat, például osztállyal
vagy struktúrával létrehozott típussal. A túlterhelő függvény egy szimpla függvény,
csakhogy elébe van írva az
operator kulcsszó, amit a túlterhelni kívánt operátor követ:



































Az operátorfüggvény általában tagfüggvény vagy
friend függvény lehet. A
(), [] és -> operátorokat csakis
nem statikus tagfüggvényekkel lehet túlterhelni, a
new és delete
operátorokat pedig statikus tagfüggvényekkel. Hogy milyen függvényt válasszunk
a túlterhelésre, az az operátortól függ.


- Amikor az operátorfüggvény tagfüggvény,
akkor a baloldali vagy az egyetlen operandus az osztályának az objektuma vagy
az arra hivatkozó referencia kell legyen. Ha a feladat úgy követlei, hogy a
baloldali operandus egy másik osztály objektuma legyen, akkor az
operátorfüggvény nem lehet tagfüggvény. Ha nem tagfüggvény, de közvetlenül el
kell érje az adott osztály privát vagy protected tagjait, akkor friend típusnak
kell deklarálni. Ha viszont az adott osztálynak van getter és setter tagfüggvénye a
privát tagváltozók módosításához, akkor nem kötelező a friend típus használata.


- Egy példa erre a és a >> operátor, melyek baloldalán be- vagy
kimeneti stream-ek vannak. A
operátornak egy ostream& típusú operandusa kell legyen bal oldalt,
mint például a
cout,
ezért az operátorfüggvénye nem lehet tagfüggvény. Ugyanez igaz a
>> operátorra is.


- Egy másik ok, hogy az operátor ne legyen
tagfüggvény, a kommutativitás. Például egy
long int típusú number objektum és egy HugeInteger típusú hugenumber objektum (amely a számítógép korlátainál
nagyobb egészeket képes összeadni) közötti összeadó művelet kommutatív kell
maradjon. A
hugenumber+number
művelethez az
operator+ függvény
maradhat tagfüggvény, de hogy a
number+hugenumber is működjön, az operátorfüggvényt az osztályon kívül kell megírni.





A >
operátor túlterhelése


      A PhoneNumber osztály a következő példából egy olyan adattípus,
amely egy 4+6 számjegyből álló telefonszámot határoz meg:





#include


using std::cout;


using std::cin;


using std::ostream;


using std::istream;


#include


using std::setw;





class PhoneNumber


{


     friend ostream&operatorconst PhoneNumber&);


     friend istream&operator>>(istream&,
PhoneNumber&);





     private:


           char areaCode[5];//4 prefix és '\0'


           char number[7]; 
//6 szam és '\0'


};





ostream&operatorout, const PhoneNumber& num)


{


     out
"/"
num.number;


     return out; // fűzér mód


}





istream&operator>>(istream&
in, PhoneNumber& num)


{


     in
>> setw(5) >> num.areaCode;


     in.ignore(1);
//figyelmen kívül hagyja a következő karaktert (/)


     in >>
setw(7) >> num.number;


     return in;    // fűzér mód


}





int main()


{


     PhoneNumber
phone;


    


     cout
"Add meg a telefonszámot 0711/123456
formátumban: "
;


    


     cin
>> phone;


     // a cin meghívja az operator>> függvényt a (cin,
phone) paraméterrel


    


     cout
"A beírt telefonszám: "
phone;


     // a cout meghívja az operatorphone) paraméterrel





     return 0;


}





A kimenet:


Add meg a
telefonszámot 0711/123456 formátumban: 0366/456231


A beírt
telefonszám: 0366/456231





Az operator>>
függvény a stream-ből (adatfolyamból) olvas ki, melynek első
paramétere egy
istream referencia, a második pedig egy PhoneNumber referencia. Az első paraméter lehetőséget ad, hogy hozzáférjünk a cin-el beolvasott adatokhoz, a második pedig,
hogy betegyük őket a privát tagváltozókba. Amikor azt írjuk, hogy
cin >> phone , akkor valójában az operator>>(cin,phone) függvény hívódik meg. A függvény
változatlanul vissza is téríti a kapott információt, így lehetőség van füzérszerűen
használni az operátort, például:
cin >> phone1 >> phone2;Az operator
függvénynél is ugyanez a helyzet, a
cout meghívásánál az operator hívódik meg. Ez a két operátorfüggvény
friend típusú kell legyen, mert a
PhoneNumberobjektum mindig jobboldali operandusként szerepel. Hogy tagfüggvények
legyenek az osztály objektuma baloldali operandusként kell szerepeljen.





Az unáris operátorok
túlterhelése


     
Az unáris (egy operandusú) operátor túlterhelő függvényét
tagfüggvényként is meg lehet írni, egy paraméterrel vagy paraméter nélkül. Ha
paramétere van, akkor az az osztály objektuma vagy az osztály objektumára hivatkozó referencia kell legyen. Legyen egy
String nevű osztály, melyben átdefiniáljuk a ! operátort, hogy leellenőrizze, hogy az
objektum üres-e vagy sem. Ha például
s a String osztály objektuma,
akkor a
!s kifejezés az s.operator!() függvényt fogja meghívni. Az
operátorfüggvényt az osztályon belül deklaráljuk:





class String


{


     public:


           booloperator!() const;


     ...


};





Ha osztályon kívül deklaráljuk, akkor
argumentumként meg kell adni az osztály objektumát vagy annak referenciáját.





class String


{


     friend booloperator!(const
String&);


     ...


};





Ebben az esetben a !s kifejezés az operator!(s) függvényt fogja meghívni. Ha
választhatunk, akkor kerüljük a friend függvények használatát.





A bináris operátorok
túlterhelése


     
A bináris (két operandusú) operátor túlterhelő függvényét
tagfüggvényként is meg lehet írni, egy vagy két paraméterrel, melyből az egyik
az osztály objektuma vagy annak referenciája. Legyen
x és y a String osztály objektuma és legyen a += operátor ezen két objektum összekapcsoló
operátora. Ha tagfüggvénynek írjuk az operátorfüggvényt, akkor az
y+=z kifejezés az y.operator+=(z) függvényt fogja meghívni.





class String


{


     public:


           const String&operator+=(const String&);


     ...


};





Ha friend-ként deklaráljuk, akkor bináris
operátorként terheljük túl és az
y+=z
kifejezés az
operator+=(y,z) függvényt
fogja meghívni.





class String


{


     friendconst String&operator+=(String&,
const String&);


     ...


};





Típusátalakítás


     
A fordító sokféle típusátalakítást ismer, ám a programozó által
definiált típusokat nem tudja átalakítani. Ezért a programozó dolga, hogy
meghatározza miként lehet az ő típusait más típusokká alakítani. Ezt
legegyszerűbb az osztály konstruktorában megvalósítani, ahol más osztályok
objektumait konvertálhatjuk a jelenlegi osztály típusára. A
String osztály konstruktora például
átalakíthatja a
char* értékeket String típusú objektummá. Erre a célra ideális a
cast operátor, amelyet csakis tagfüggvényben
alkalmazhatunk. A függvény prototípusa:





A::operator char*()
const;





Ez egy cast túlterhelő függvényt (operátorfüggvényt)
deklarál, melyekkel ideiglenes
char* típusú objektumok kreálhatók az A típusú objektumból. Nem kell meghatározni
a visszatérített típust, hisz az az objektum átkonvertált típusa lesz. Amikor a
fordító találkozik a
(char*) s kifejezéssel, meghívja az s.operator char*() tagfüggvényt.


     
A
cast és a konverziós
operátorok egyik hasznos tulajdonsága, hogy valahányszor szükség van rájuk, a
fordító meghívja őket hogy ideiglenes objektumokat hozzon létre. Például ha az
s objektum a String osztályból olyan helyen jelenik meg, ahol
valójában
char* kéne legyen, mint például a cout kifejezésben, akkor a fordító meghívja a
túlterhelt
cast operátort, hogy
átalakítsa az objektumot
char* típusba. Ha létezik ez az
operátorfüggvény a
String
osztályban, akkor nincs is már szükség a
operátor túlterhelésére a String objektumok kiírásához.





A String osztály


     
A
String osztály a C++
standard könyvtárának része. Ettől függetlenül, a következő példában egy saját 
String osztály van megvalósítva, amely bemutatja
az operátorok túlterhelését.





string1.h


#ifndef STRING1_H


#define STRING1_H


#include


using std::ostream;


using std::istream;





class String


{


     friend ostream& operatorconst String&);


     friend istream& operator>>(istream&,
String&);





     public:


          


           String(const char* = ""); //átalakító konstruktor: char* -> objektum


           String(const String&);   
//másoló konstruktor


           ~String();


          


           const String& operator=(const String&);      //érték adás


           const String& operator+=(const String&);     //összekapcsolás


          


           bool operator!() const;                      //üres-e ?


           bool operator==(const String&) const;
       //s1==s2
?


           bool operatorconst String&) const;         //s1?


           bool operator!=(const String& right) const
  //s1!=s2 ?


           {


                return !( *this ==
right );


           }


           bool operator>(const String& right) const    // s1>s2 ?


           {


                return right this;


           }


           bool operatorconst String& right) const
  //
s1


           {


                return !( right this
);


           }


           bool operator>=(const String& right) const
  //
s1>=s2 ?


           {


                return !( *this right );


           }


               


           char& operator[](int);               //indexelés


           const char& operator[](int) const;   //indexelés


           String
operator()(int,
int);         //substringet térít vissza


           int getLength() const;               //a
string hossza


          


     private:


          


           int length;                     //string hossz


           char* sPtr;                     //mutató a string elejére


           void setString(const char*);    //segítő függvény:
beállítja az sPtr mutatót


};


#endif





string1.cpp


#include


using std::cout;


using std::endl;


#include


using std::setw;


#include


#include


#include"string1.h"





//Átlakító konstruktor:
char*->objektum


String::String(const
char* s) : length(strlen(s))


{


     cout
"Átalakító konstruktor: "

'\n';


     setString(s);
//beállítja az sPtr mutatót az s elejére


}





//Másoló konstruktor


String::String(const
String& copy) : length(copy.length)


{


     cout
"Másoló konstruktor: "

'\n';


     setString(copy.sPtr);


}





//Destruktor


String::~String()


{


     cout
"Destruktor: "
sPtr '\n';


     delete[] sPtr; //memória
felszabadítás


}





//Az = operátor túlterhelése:
stringek másolása


const String& String::operator=(const String& right)


{


     cout
"Az = operátor meghívódott\n"
;


     if(&right != this)   //ha nem
saját magával tettük egyenlővé


     {


           delete[] sPtr;  //a régi string törlése (ha netán volt tartalma)


           length
= right.length;//az új string hossza


           setString(right.sPtr);//az új string mutatója


     }


     else


           cout
"Nem tehető saját magával
egyenlővé\n"
;


     return *this; //fűzér mód


}





//A += operátor túlterhelése:
stringek összekapcsolása


const String& String::operator+=(const String& right)




This post first appeared on Altair Gate - News, please read the originial post: here

Subscribe to Altair Gate - News

Get updates delivered right to your inbox!

Thank you for your subscription

×