Преобразование типов Макаревич Л. Г.
Операция приведения типов Тип ( выражение ) Тип ( выражение ) (тип) выражение (тип) выражение int a = 5; float b = 6.8; a = b;// предупреждение a = (int) b; Real Time Type Identification RTTI
Операция const_cast Операция удаляет модификатор const const_cast (выражение) Операция удаляет модификатор const const_cast (выражение) Ответственность за неизменность параметра в функции несет программист Ответственность за неизменность параметра в функции несет программист error C2664: 'f' : cannot convert parameter 1 from 'const int *' to 'int *' void f(int * p ) { cout
Операция dynamic_cast dynamic_cast (выражение) dynamic_cast (выражение) Применяется для преобразования указателей родственных классов иерархии ( указателя базового класса в указатель на производный ) Применяется для преобразования указателей родственных классов иерархии ( указателя базового класса в указатель на производный ) Понижающее преобразование – из базового в производный Понижающее преобразование – из базового в производный Повышающее преобразование – из производного в базовый Повышающее преобразование – из производного в базовый Перекрестное преобразование – между производными классами с одним базовым или между базовыми одного производного Перекрестное преобразование – между производными классами с одним базовым или между базовыми одного производного
Повышающее преобразование class B { }; class C: public B{ }; int main(int argc, char* argv[]) { C * c = new C; B * b = dynamic_cast (c); b = c; return 0; }
Понижающее преобразование class B { public: virtual void f1(){cout
/GR To set this compiler option in the Visual Studio development environment Open the project's Property Pages dialog box. For details, see Setting Visual C++ Project Properties.Setting Visual C++ Project Properties Click the C/C++ folder. Click the Language property page. Modify the Enable Run-Time Type Info property.
class A { public: virtual ~A(){} }; class B: public virtual A{}; class C: public virtual A{}; class D: public B, public C{}; void demo(A *a) { D * d = dynamic_cast (a); if ( d) { } int main(int argc, char* argv[]) { D * d = new D; demo (d); delete d; return 0; }
class A {public: virtual void f1(){} }; class B: public A{ public:void f2(){} }; void demo(A &a) {try { B & b = dynamic_cast (a); // при преобразовании ссылки //выбрасывается исключение bad_cast b.f2(); }catch(bad_cast){cout
Перекрестное преобразование class A { public: virtual void f1(){} }; class B: public A{ public: void f2(){} }; class C: public A{ public: void f3(){} }; void demo(C * p) { B* c = dynamic_cast (p); if (c) c->f2(); else cout
class A { public: virtual void f1(){} }; class B { public: virtual void f2(){} }; class C: public A, public B{ public: void f3(){} }; void demo(A * p) { B* c = dynamic_cast (p); // преобразование между базовыми классами if (c) c->f2(); else cout
bad_cast The bad_cast exception is thrown by the dynamic_cast operator as the result of a failed cast to a reference type. catch (bad_cast) statement The interface for bad_cast is: class _CRTIMP bad_cast : public exception { public: bad_cast(const __exString& what_arg) : exception (what_arg) {} };
The following code contains an example of a failed dynamic_cast that throws the bad_cast exception. // compile with: /EHsc /GR #include #include class Shape { public: virtual void virtualfunc() const {} }; class Circle: public Shape { public: virtual void virtualfunc() const { }; }; using namespace std; int main() { Shape shape_instance; Shape& ref_shape = shape_instance; try { Circle& ref_circle = dynamic_cast (ref_shape); } catch (bad_cast) { cout
static_cast преобразование типов на этапе компиляции static_cast (выражение) float f = 100; int i = static_cast (f); class B {}; class C: public B{}; C c; B *bp = static_cast ( c ); B b; C &cp = ctatic_cast ( b ); static_cast (выражение) float f = 100; int i = static_cast (f); class B {}; class C: public B{}; C c; B *bp = static_cast ( c ); B b; C &cp = ctatic_cast ( b );
reinterpret_cast reinterpret_cast (выражение) Опасные преобразования – на совести программиста char *p = reinterpret_cast malloc(100); long l = reinterpret_cast (p); reinterpret_cast (выражение) Опасные преобразования – на совести программиста char *p = reinterpret_cast malloc(100); long l = reinterpret_cast (p);
Динамическое определение типа – операция typeid и класс typeinfo typeid (тип) typeid (тип) typeid (выражение) typeid (выражение) Операция возвращает ссылку на объект typeinfo. При ошибке порождается исключение bad_typeid. Операция возвращает ссылку на объект typeinfo. При ошибке порождается исключение bad_typeid. include include
The type_info class describes type information generated within the program by the compiler. Objects of this class effectively store a pointer to a name for the type. The type_info class also stores an encoded value suitable for comparing two types for equality or collating order. The encoding rules and collating sequence for types are unspecified and may differ between programs. The typeinfo.h header file must be included in order to use the type_info class. The interface for the type_info class is: class type_info { public: virtual ~type_info(); int operator==(const type_info& rhs) const; int operator!=(const type_info& rhs) const; int before(const type_info& rhs) const; const char* name() const; const char* raw_name() const; private: type_info(const type_info& r); type_info& operator=(const type_info & r); };
You cannot instantiate objects of the type_info class directly, because the class has only a private copy constructor. The only way to construct a (temporary) type_info object is to use the typeid operator. Since the assignment operator is also private, you cannot copy or assign objects of class type_info. The operators == and != can be used to compare for equality and inequality with other type_info objects, respectively. There is no link between the collating order of types and inheritance relationships. Use the type_info::before member function to determine the collating sequence of types. There is no guarantee that type_info::before will yield the same result in different programs or even different runs of the same program. In this manner, type_info::before is similar to the address-of (&) operator. The type_info::name member function returns a const char* to a null-terminated string representing the human-readable name of the type. The memory pointed to is cached and should never be directly deallocated. The type_info::raw_name member function returns a const char* to a null- terminated string representing the decorated name of the object type. The name is actually stored in its decorated form to save space. Consequently, this function is faster than type_info::name because it doesn't need to undecorate the name. The string returned by the type_info::raw_name function is useful in comparison operations but is not readable. If you need a human-readable string, use the type_info::name function instead. Type information is generated for polymorphic classes only if the /GR (Enable Run- Time Type Information) compiler option is specified.
class A { public: virtual ~A(){} }; class B: public A { public: virtual void f2(){} }; void demo(A * p) { if ( typeid(*p)==typeid(B)) { dynamic_cast (p)->f2(); } cout
B * b = new B; cout
bad_typeid The bad_typeid exception is thrown by the typeid operator when the operand for typeid is a NULL pointer. catch (bad_typeid) statement The interface for bad_typeid is: class _CRTIMP bad_typeid : public exception { public: bad_typeid(const char * what_arg) : exception (what_arg) {} }; // compile with: /EHsc /GR #include class A{ public: // object for class needs vtable // for RTTI virtual ~A(); }; using namespace std; int main() { A* a = NULL; try { cout