CPP {类型强转,reinterpret_cast,static_cast}
@LOC_1
@LOC: 2
static_cast
性质
ST * s = new ST
此时static_cast<ST*>(s) != nullptr
, 而如果你s = nullptr
后 会发现static_cast<ST*>(s) == nullptr
这说明 他看的 不是ST *
这个静态类型 而是看他的值;
@DELI;
static_cast<T>(a)
和(T)a
方式, 并不是等价的; (比如@LINK: @LOC_0
);
reinterpret_cast
定义
#用途1#
指针的强转, 从void*
转换成T*
;
.
将T*
转换为void*
这是可以隐式强转的, 但反过来 给你一个void*
(但前提是你知道 他本质上是T*
), 他不可以直接强转到T*
, 那么此时 这就可以T* = reinterpret_cast<T*>(void*)
;
#用途2#
将指针的地址 转换为 整数类型;
.
我们知道 指针可以输出(16进制的地址), 但如果我们想得到其地址对应的整数呢? 此时static_cast<int64>(&p)
是不可以的 (但(int64)&p
是可以的…), 但还可以使用reinterpret_cast<int64>( &p)
; (@MARK: @LOC_0
);
类型强转
性质
@LINK: https://editor.csdn.net/md/?articleId=126769957-(@LOC_0)
;
T, unsigned T
混合时 会自动转为unsigned T
;
@DELI;
(Mod)-1
, 她会调用Mod(int)
这个构造函数; 即她和Mod(-1)
的效果是一样的;
(int)Mod()
, 她会调用Mod.int()
这个类型强转运算符;
int( Mod())
, 这是错误语法, 因为int
并没有一个接受Mod
的构造函数;
错误
@DELI;
有符号整型的负数 进行强转, 他很智能… 会保持值不变, 而不是直接的比特位复制;
int8 a = -1
, 执行int32 b = a;
你是否会认为, b
的低8位就是a
然后高位都是0
, 即00 00 00 FF
, 这是错误的; 他的强转 是要保证值不变的, 即原来a==-1
, 现在一定也b==-1
, 即b = F...F
;
.
只有涉及到有符号数的负数时 会这样, 其他情况的话 比如当a >= 0
时, 此时确实是: b
的低8位就是a
然后高位都是0
, 这很符合直觉…
@DELI;
MARK: @LOC_1
;
class A{
A( double a); // double可以*隐式*强转给A
operator double() const; // A可以*隐式*强转给double
A operator*( A _a){ ...}
};
A a;
(int/double) b
;
1: 对于b * a
, 他等价于: b * (double)a
, a
被隐式强转为了double
, 他不会使用A的乘法规则; (比如2*a, 2.0*a
都是使用的double
的乘法规则 不是A的);
2: 对于a * b
, 此时有产生歧义! 有2个乘法规则都可以使用 因此冲突了, 一个是(double)a * b
(即A被隐式强转为了double
他使用的是double
的乘法), 令一个是a * (A)b
(即b
隐式强转为了A类型 他使用的是A
的乘法);
此时 错误还是挺多的:
+: 上面的1:
, 我们想让他调用我们自己的A
的乘法规则 但是他却把A给隐式强转给了double
; 解决办法是: 取消A的隐式强转;
+: 上面的2:
, 我们选择这2个歧义版本中的 A的乘法这个;
综上 解决办法是: 将强转运算符重载 改为显式, 即explicit operator double() ...
, 这样对于a*b/ b*a
他只会对应A的乘法规则;
应用
@DELI;
#类型运算符重载#
MARK: @LOC_0
;
class A{
[explicit] operator double() const{ return 3.33;}
};
A a;
, 此时A可以强转为double
, 即(double)a, double(a)
这2种方式 都会调用上面这个运算符函数
规范: 强转运算符重载 必须要带explicit
显式; (参见: LINK: @LOC_1
)