c++ - 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 如何在幕后工作以及它与内存(因此是对象)和(如果需要)发生的指令的关系?
解决方案
考虑两种不同的用例可能会有所帮助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
的变量。union
U
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"
很好是因为x
is avoid*
可以指向任何(非功能)实体,所以它可以指向 a 是合理的double
。
推荐阅读
- api - IBM Cloud API:如何获取 IBM ID/用户的 IAM-id?
- java - 无法从 START_ARRAY 令牌中反序列化 POJO 实例
- jquery - SearchPane 列显示的数据表问题
- ios - 是否存在某种方式来获取来自 json 或 swift 文件的测试数据,仅用于预览提供者?
- dialogflow-es - 传递函数触发器时出错。参考错误:未定义客户端 ID
- python - 为什么 SocketIO 和 SSLify 不能一起工作?
- c# - 在 c# wpf 中键绑定到按钮元素
- azure - 使用具有 azure 功能的 azure service bus 进行 ERP 订单导入的最佳方法
- amazon-cloudformation - 使用 CDK 为管道 github 源 webhook 动态设置 targetPipelineVersion
- c++ - C ++函数将基类指针解析为派生类指针