?,c++,object,casting"/>

首页 > 解决方案 > static_cast 有什么区别和静态类型?

问题描述

到目前为止,我理解这static_cast是一个编译时操作,它以某种方式分析实体的内存并尝试将其转换为指定的对象。

我看到 static_cast 广泛用作static_cast<T *>. 这是什么原因?是因为编译器需要一个指针来检查对象的内存布局吗?

例子:

union U { int a; double b; } u;
void* x = &u;                        // x's value is "pointer to u"
double* y = static_cast<double*>(x); // y's value is "pointer to u.b"
char* z = static_cast<char*>(x);     // z's value is "pointer to u"

然而,static_cast<T>这失败了:

double yy = static_cast<double>(u); error: cannot convert 'union U' to 'double' without a conversion operator

我首先在类的使用中发现了这种类型的转换,并且看起来它在那里使用得更多。

Derived * d = new Derived();
Base * b = static_cast<Base *>(d);

然而,同样的问题仍然存在:

Base b1 = Base();
Derived d2 = Derived();

b1 = static_cast<Base>(d2);
// No error here

我能否详细说明 static_cast 如何在幕后工作以及它与内存(因此是对象)和(如果需要)发生的指令的关系?

标签: c++objectcasting

解决方案


考虑两种不同的用例可能会有所帮助static_cast:一种用于将非指针类型转换为另一种,另一种用于将指针类型转换为另一种。

将非指针类型相互转换时,static_cast其含义是“进行从源值初始化目标类型的对象时会进行的那种转换”。因此,例如,在此代码中:

int aASCII = 64;
cout << static_cast<char>(aASCII) << endl; // Prints 'A'

意思是static_cast<char>(aASCII)“给我一个char值,如果我要初始化一个新char值到这里aASCII。” 这类似于执行以下操作:

int aASCII = 64;
char temp = aASCII;
cout << temp << endl;

同样,考虑以下代码:

int total = 137;
int numItems = 42;
cout << static_cast<double>(total) / numItems << endl;

该位的意思是“在进行除法时static_cast<double>(total)假装这total是此处”。double这类似于写作

int total = 137;
int numItems = 42;
double temp = total;
cout << temp / numItems << endl;

考虑到这一点,为什么这段代码不能编译?

double yy = static_cast<double>(u); // Oops!

原因是这有点像写作

double temp = u; // Oops, doesn't compile
double yy = temp;

在这里,这不会编译,因为您无法将 a 初始化为typedouble的变量。unionU

with 指针的static_cast使用使用了一组不同的规则。使用指针时,static_cast意味着“请假装指针指向我希望它指向的类型的对象,但前提是存在一些可行的宇宙。” 因此,例如,这是完全合法的:

Base* ptr = new Derived;
Derived* dPtr = static_cast<Derived*>(ptr);

在这里,这说“我有一个类型的指针Base*。有一个合理的世界,它确实指向 a Derived。请将指针转换为 a Derived*,但不要进行任何运行时检查以确保这是安全的。我是请注意,如果这实际上并不指向 a Derived,那么将会发生坏事。”

但是,您不能这样写:

float* ptr = new float[137];
Derived* dPtr = static_cast<Derived*>(ptr); // Error!

这是行不通的,因为类型的指针float*无法指向一个Derived对象(在某个时间点不对某个指针做一些非常可怕的事情)。

你的代码的原因

double* y = static_cast<double*>(x); // y's value is "pointer to u.b"

很好是因为xis avoid*可以指向任何(非功能)实体,所以它可以指向 a 是合理的double


推荐阅读