C++ 中有两个根本不同的概念,它们有时都被称为“转换”:一个是转换,一个是重新解释。
转换会创建一个与现有对象具有“相同值”但类型不同的新对象。以下是一些示例:
示例 1:类型提升
// 1a: promote int to double to get the correct type of division
int numerator = rand(), denominator = rand();
double d = double(numerator) / double(denominator);
// 1b: convert int to double to achieve a particular argument deduction
int n;
template <typename T> void do_numeric_stuff(T x) { /* ... */ }
do_numeric_stuff(double(n));
示例 2:派生到基础的转换
struct B { }; struct D : B { };
D x;
D * p = &x; // pointer to x
B * q = p; // implicit conversion; may change the value!
另一方面,重新解释允许我们将一个变量视为另一个变量。唯一正确和有用的应用程序是序列化,以一种或另一种形式。
示例 3:序列化
std::ofstream file("output.bin"); // output file
char large_buffer[HUGE]; // in-memory buffer
unsigned int n = get_data();
char const * p = reinterpret_cast<char const *>(&n);
file.write(p, p + sizeof n); // write the bytes of `n`
std::copy(p, p + sizeof n, large_buffer); // ditto
std::copy(large_buffer + 17, large_buffer + 17 + sizeof n,
reinterpret_cast<char *>(&n)); // repopulate `n` from buffer
标准规定,通过不正确类型的指针访问对象是未定义的行为(也称为“类型双关语”)。虽然可以将对象指针存储在void* 中,然后将其转换回来并使用它,但不可以将浮点数视为整数等。 唯一可以接受的方式来访问一个对象,就好像它是另一个对象是我演示的那样,即将T 类型的对象当作一个数组char[sizeof(T)] 处理——也就是说,你是允许访问每个对象的底层二进制表示。