Преобразуване на типове

7. Преобразуване на типове

В стандарта на C++ има четири операции за преобразуване на типовете. За предпочитане е те да се използват вместо старото преобразуване, включено в C и C++ - въпреки, че са по-малко мощни, те са по-конкретни, което дава възможност за по-точен контрол. Преобразуването в C е едно за всички случаи. Дали това е хубаво или лошо нещо, е въпрос на лично мнение.

static_cast

static_cast е за преобразуване на типа, когато проверката на типа се извършва по време на компилация. Извършва стандартни преобразувания. Например void* → char* и обратно. Извършването на неразрешено преобразуване е синтактична грешка. Неразрешено е преобразуването от константни в неконстантни типове, типове на указатели и псевдоними, в типове, които не са в отношение на открито наследяване, преобразуване в тип без конструктор или предефинирана операция1.

Пример:

#include <iostream>
 
using std::cout;
using std::endl;
 
class BaseClass 
{
public:
    void f () const
    { cout << “Base” << endl; }
} ;
 
class DerivedClass : public BaseClass 
{
public:
    void f () const
    { cout << “Derived” << endl; }
} ;
 
void test (BaseClass *);
 
void main ()
{
    double d = 8.22;
    int x = static_cast < int > (d);
    cout << “d = “ << d << endl
    << “x = “ << x << endl;
    BaseClass *basePtr = new DerivedClass;
    test (basePtr);
    delete basePtr;
}
 
void test (BaseClass *basePtr)
{
    DerivedClass *derivedPtr;
    derivedPtr = static_cast <DerivedClass*> (basePtr);
    derivedPtr -> f ();
}

извършва се понижаващо преобразуване( down cast ) на указател от базовия клас в указател на производния – което е опасно, но static_cast го позволява. Нищо не гарантира, че обектът в derivedPtr може да се използва като DerivedClass. От програмиста зависи да осигури тази гаранция. static_cast е по-несигурно, но по-бързо от dynamic_cast, защото по време на изпълнение не се проверява дали преходът е коректен.

const_cast

const_cast маха const или volatile чрез преобразуване. По този начин, една const стойност може да бъде използвана като обикновена, включително и да бъде променяна. Използва се когато дадена функция приема променлива от тип Т, но разполагаме с променлива от тип const T.

Променлива, която е декларирана константна (const int a = 10) може да бъде променяна по този начин, но поведението не е дефинирано по стандарт. Възможно е да се изведе съобщение за грешка.
Променлива, която е декларирана без const модификатор, в някой момент го е получила, а после е била взета с const_cast - може да бъде променяна без проблеми.

Пример за употреба на const_cast.

#include <iostream>
using namespace std;
 
void f(int* p) {
  cout << *p << endl;
}
 
int main(void) {
    const int a = 10;
    const int* b = &a;
 
    // f() очаква int*, не const int*
    //   f(b);
    int* c = const_cast<int>(b);
    f(c);
 
    //  *b е констнанта, следващият ред не е валиден.
    //  *b = 20;
 
    // По стандарт не е дефинирано какво ще стане тук
    //  *c = 30;
 
    int a1 = 40;
    const int* b1 = &a1;
    int* c1 = const_cast<int>(b1);
 
    // a1, това към което сочи c1, не е декларирана константна
    *c1 = 50;
 
    return 0;
}

reinterpret_cast

reinterpret_cast се използва за нестандартни преобразувания. От един тип указател към друг. Не може да се използва за стандартни преобразувания. ( double → int ). Почти никога не се използва, защото възможностите, които предоставя са твърде непредвидими. Може да преобразува от указател към произволен клас, в указател към произволен друг. В почти всички случаи това е нещо лошо, по същите причини, поради които и със static_cast трябва да се внимава. Единствената безопасна употреба на резултата от reinterpret_cast е да се върне обратно в базовия тип.

Пример:

#include <iostream>
 
using std::cout;
using std::endl;
 
void main()
{
    int x = 120;
    int *ptr = &x;
    cout << reinterpret_cast< char* > ( ptr ) << endl;
}

В случая преобразува int* → char*. Може да се използва преобразуване на указател в цяло число(друг указател, short, int) и обратно. Като цяло, това е опасно. Освен всичко друго една и съща програма с reinterpred_cast може да се изпълнява различно на различни платформи.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License