Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

Direction d = static_cast<Direction>(3.14); // d is RIGHT

Section 91.8: Derived to base conversion for pointers to members

A pointer to member of derived class can be converted to a pointer to member of base class using static_cast. The types pointed to must match.

If the operand is a null pointer to member value, the result is also a null pointer to member value.

Otherwise, the conversion is only valid if the member pointed to by the operand actually exists in the destination class, or if the destination class is a base or derived class of the class containing the member pointed to by the operand. static_cast does not check for validity. If the conversion is not valid, the behaviour is undefined.

struct A {};

 

 

 

struct B { int x; };

 

 

struct C : A, B { int y; double z; };

 

 

int B::*p1 =

&B::x;

 

 

int C::*p2 =

p1;

//

ok; implicit conversion

int B::*p3

=

p2;

//

error

int B::*p4

=

static_cast<int B::*>(p2);

//

ok; p4 is equal to p1

int A::*p5

= static_cast<int A::*>(p2);

//

undefined; p2 points to x, which is a member

 

 

 

// of the unrelated class B

double C::*p6 = &C::z;

 

 

double A::*p7 = static_cast<double A::*>(p6); //

ok, even though A doesn't contain z

int A::*p8

=

static_cast<int A::*>(p6);

//

error: types don't match

 

 

 

 

 

Section 91.9: void* to T*

In C++, void* cannot be implicitly converted to T* where T is an object type. Instead, static_cast should be used to perform the conversion explicitly. If the operand actually points to a T object, the result points to that object. Otherwise, the result is unspecified.

Version ≥ C++11

Even if the operand does not point to a T object, as long as the operand points to a byte whose address is properly aligned for the type T, the result of the conversion points to the same byte.

// allocating an array of 100 ints, the hard way

int* a = malloc(100*sizeof(*a));

// error; malloc returns void*

int* a = static_cast<int*>(malloc(100*sizeof(*a))); // ok

// int* a = new int[100];

// no cast needed

// std::vector<int> a(100);

// better

const char c = '!';

 

const void* p1

= &c;

 

const char* p2

= p1;

// error

const char* p3

= static_cast<const char*>(p1); // ok; p3 points to c

const int* p4 = static_cast<const int*>(p1);

// unspecified in C++03;

 

 

// possibly unspecified in C++11 if

 

 

// alignof(int) > alignof(char)

char* p5 = static_cast<char*>(p1);

// error: casting away constness

GoalKicker.com – C++ Notes for Professionals

486

Section 91.10: Type punning conversion

A pointer (resp. reference) to an object type can be converted to a pointer (resp. reference) to any other object type using reinterpret_cast. This does not call any constructors or conversion functions.

int x = 42;

 

char* p = static_cast<char*>(&x);

// error: static_cast cannot perform this conversion

char* p = reinterpret_cast<char*>(&x); // OK

*p = 'z';

// maybe this modifies x (see below)

 

 

Version ≥ C++11

The result of reinterpret_cast represents the same address as the operand, provided that the address is appropriately aligned for the destination type. Otherwise, the result is unspecified.

int x = 42;

char& r = reinterpret_cast<char&>(x); const void* px = &x;

const void* pr = &r;

assert(px == pr); // should never fire

Version < C++11

The result of reinterpret_cast is unspecified, except that a pointer (resp. reference) will survive a round trip from the source type to the destination type and back, as long as the destination type's alignment requirement is not stricter than that of the source type.

int x = 123;

unsigned int& r1 = reinterpret_cast<unsigned int&>(x); int& r2 = reinterpret_cast<int&>(r1);

r2 = 456; // sets x to 456

On most implementations, reinterpret_cast does not change the address, but this requirement was not standardized until C++11.

reinterpret_cast can also be used to convert from one pointer-to-data-member type to another, or one pointer- to-member-function type to another.

Use of reinterpret_cast is considered dangerous because reading or writing through a pointer or reference obtained using reinterpret_cast may trigger undefined behaviour when the source and destination types are unrelated.

GoalKicker.com – C++ Notes for Professionals

487