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

Típus átalakítás


      Az adat típusának átalakítását egy másik típusra type-cast-nak nevezik. Két típusú átalakítás
lehetséges: az implicit és explicit átalakítás. Az implicit átalakításhoz nincs
szükség
cast-re, mert az
átalakítás automatikusan megtörténik a másolásnál ha a cél memóriahelye
kompatibilis adattípust tárol.





short a=2000;


int b;


b=a;





Ebben a példában a short típusú változó int típussú változóvá alakult. A hasonló átalakítások
néha veszítenek az adatok pontosságából, de ezt a fordító jelzi. Nem csak az
alapvető adattípusokat lehet átalakítani, hanem az osztály típusú adatokat is.





class A {};


class B {
public: B (A a) {} };


A a;


B b=a;





A B osztály konstruktora egyetlen A típusú objektumot használ paraméternek, így B objektuma hasonló lesz A objektumával és az átalakítás lehetséges.





Az eltérő értelmezést igénylő átalakítások
explicit átalakítások kell legyenek és ezek kétféleképp is meghatározhatóak:





short a=2000;


int b;


b = (int) a;


b = int (a);





Ezt e két operátor bármilyen átalakításnál
használható, ide értve az osztály-osztály és mutató-osztály átalakítást. Habár
egy ilyen átalakítás szintaktikailag helyes, mégis hibát vagy redundáns
kimenetet eredményezhet.





#include


using namespace std;





class A {


     float i,j;


};





class B {


     int x,y;


     public:


           B
(int a, int b)
{ x=a; y=b; }


           int result() { return
x+y;}


};





int main () {


     A d;


     B *
padd;               //
padd egy B típusú mutató


     padd
= (B*) &d;         // padd az A típusú objektumra (d) mutat


     cout
result(); // az A osztálynak nincs
is result() függvénye


                             // mégsem jelez hibát a fordító


     return 0;


}





A fenti programban A és B
osztály nem kompatibilisek egymással. Ennek ellenére az
A objektumát (d) át lehet konvertálni, hogy a B mutatója (padd) rá mutasson. A padd használhatatlanná válik, és a fordító ezt
nincs honnan lássa.





A static_cast operátor





     
A standard C++ alapvetően négy
cast operátort tartalmaz: static_cast, const_cast, reinterpret_cast és dynamic_cast. Az újabbak kevésbé használatosak, már csak azért
is hogy nincsenek ennyire általánosítva. Az implicit átalakításhoz hasonlóan
itt sem lehet szintaxis hibát észlelni egy hibás átalakításnál, viszont a
fordítás során minden adattípus ellenőrzésre kerül. A static_cast operátor a
standard adattípusok közti átalakításra jó, mint például
void* -> char* vagy int -> double és ezek fordítottjai.





#include


using std::cout;


using std::endl;





class BaseClass


{


     public:


           void f() const { cout
"Ősosztály\n"
; }


};





class DerivedClass : public
BaseClass


{


     public:


           void f() const { cout
"Derivált osztály\n"
; }


};





void test(BaseClass*);





int main()


{


     double d = 8.22;


     int x = static_castint>(d); // d átalakítása int-re





     cout
"d = "
"\nx = "


    


     BaseClass
*basePtr = new DerivedClass; //memóriafoglalás


     test(basePtr);
//egy globális függvény


     delete basePtr; //memória
felszabadítás


    


     return 0;


}





void test(BaseClass *basePtr)


{


     DerivedClass
*derivedPtr; //derivalt osztály típusó mutató


     //az ősosztály típusú mutatót átalakítjuk derivált típusú mutatóvá


     derivedPtr
= static_cast(basePtr);


     derivedPtr->f();
//az f a derivált osztályból fog lefutni


}





A kimenet:


d = 8.22


x = 8


Derivált osztály





A BaseClass *basePtr = new
DerivedClass
utasítás
létrehoz egy
BaseClass típusú mutatót és rögtön rá is irányítja egy DerivedClass típusú objektumra. Ezután a mutató mint
paraméter jut el a
test
függvénybe, ahol értékét leadja egy
DerivedClass típusú mutatónak. Ehhez a static_cast segítségével ő maga is át kell alakuljon DerivedClass típussá. Ezt a műveletet downcast-nak nevezik, mert felső osztálytípusból
alsó osztálytípusba történt az átalakítást. Ez általában veszélyes művelet,
mert a programozónak előbb biztosra kell tudnia, hogy az objektumok
kompatibilisek egymással, ebben az esetben például mindkét osztálynak
rendelkeznie kell az
f()
függvénnyel.





virtuális függvényeket meghívó virtualViaPointer és virtualViaReference függvények esetén a
fordító nem tudja meghatározni, hogy milyen típusú lesz a baseClassPtr objektum, ami akár problémák a forrása is lehet.





A const_cast operátor





     
A
const és volatile típusu adatok átalakítására jó. A
következő programban a
const_cast egy osztály tagváltozóját alakítja át, egy const tagfüggvény révén, amely normális esetben
nem változtathatná meg az objektum felépítését.





#include


using std::cout;





class ConstCastTest


{


     public:


           void setNumber(int);


           int getNumber() const;


           void printNumber() const;


     private:


           int number;


};





void ConstCastTest::setNumber(int num) { number = num; }





int ConstCastTest::getNumber() const { return
number; }





void ConstCastTest::printNumber() const


{


     cout
"\nprintNumber() = "
;


     //a number módosítás hibát adna, mert a függvény const


     const_cast(this)->number--;


     cout


}





int main()


{


     ConstCastTest
x;


     x.setNumber(8);


     cout
"getNumber() = "
x.getNumber();


     x.printNumber();


    


     return 0;


}





A kimenet:


getNumber() = 8


printNumber() = 7





A ConstCastTest osztály három publikus tagfüggvényt és egy privát tagváltozót tartalmaz.
Két tagfüggvény konstans, ami azt jelenti, hogy nem változtathat semmit a
tagváltozón. A
printNumber függvényben a const_cast(this)->number-- utasítás ezt mégis lehetővé teszi. A this egy ConstCastTest típusú konstans mutató, mely konstans mivoltát a const_cast ideiglenesen feloldja és ezért módosítani
lehet a
number értékét. A fordító
nem jelez hibát. A
const_cast operátort nem lehet közvetlenül konstans változón használni, hanem
konstans mutatókkal vagy konstans referenciákkal működik, például:





int i = 8;


const int& ref =
i;


const_castint&>(ref)=7;


cout "\ni = "





A const_cast operátor konstans paraméter átadására is
használható nem-konstans paramétert váró függvénynek.





#include


using namespace std;





void print (char *
str){ cout





int main ()


{


     const char * c = "Konstans sor";


     print
( const_castchar

*> (c) );


     return 0;


}





A reinterpret_cast
operátor





     
A nem standard átalakítások a
reinterpret_cast operátorral történnek. Inkább különböző típusú
mutatók között végez átalakítást, a standard típusokkal nem működik, mint a
double -> int.





#include


using std::cout;


#include





int main()


{


     int x = 160;


     int *ptr = &x;


    


     cout
reinterpret_cast
char*>(ptr);


    


     return 0;


}





A kimenet:


á





A fenti programban a ptr mutató az x címével van inicializálva. Mindkettő int típus. A reinterpret_cast a mutatót char típussá alakítja. Ettől az x
értéke
char-ként lesz értelmezve
és az eredmény az
x
értékének ASCII kódja, ami éppen az
á betű. Mivel a reinterpret_cast platform-függő, előfordulhat hogy egy-egy platformon másképp viselkedik.





Run-Time Type Information
(RTTI)





     
Az RTTI lehetővé teszi egy objektum típusának meghatározását a program
futása alatt. A következő példák a
typeid és a dynamic_cast operátorokat mutatják be:





#include


using std::cout;


using std::endl;


#include





template class T>


T maximum(T value1, T value2, T value3)


{


     T max
= value1;


     if(value2 > value1) max = value2;


     if(value3 > max) max = value3;


     const char* dataType
= typeid(T).name();



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

Share the post

Típus átalakítás

×

Subscribe to Altair Gate - News

Get updates delivered right to your inbox!

Thank you for your subscription

×