essay | tech | year-summary | about
日期:2020-05-21T00:00:00Z
无论是在cpp中,还是c#中,静态强类型语言都会涉及到一个问题,就是强类型转换。
譬如下面的代码
double d = 3.3;
int i = (int)d; // i = 3;
当然,c#中,是存在比较安全的转换的,就是as
使用as,如果可以转换,会发生转换。如果不可以转换,那么就会返回一个null。
它等价于下面的式子
E as T
E is T ? (T)(E) : (T)null
它的好处是,不会在类型转换失败的时候抛出异常。
在cpp11中,引入了新的概念来进行更安全的cast。
在讨论新的cast(也不算新,已经快10年了)之前,我们先讨论已有的转换
int i = 6;
double d = i; // d = 6.0
i = d; // error, mscpp会报错
double c = 3.1415
int pai = (int)c; // pai = 3;
double d = 3.1415926;
int j = 10;
double res = d * j; // res = 31.415926
整个式子都会被作为double来计算。
int j = 10;
long long p = 1000;
long long res = p + j; // res = (long long)p + (long long)j
int ia[10];
int* ip = ia; //ia被转换成pointer然后带入ip中
但是,array被用作decltype关键字参数,或者&、sizeof、typeid等的运算对象时候,不会进行上述转换。
(与c不同之处)
正因为显示转换存在危险性,所以cpp11中引入了新的概念。
cpp11的理由主要是要把旧的cast的几种不同的cast分解开来,
把危险的reinterpret_cast分解到一个单独的操作中去,以避免显式cast所造成的不必要的困扰。
//atltime.h
static const ULONGLONG Millisecond = 10000;
static const ULONGLONG Second = Millisecond * static_cast<ULONGLONG>(1000);
static const ULONGLONG Minute = Second * static_cast<ULONGLONG>(60);
static const ULONGLONG Hour = Minute * static_cast<ULONGLONG>(60);
static const ULONGLONG Day = Hour * static_cast<ULONGLONG>(24);
static const ULONGLONG Week = Day * static_cast<ULONGLONG>(7);
适合除了const值以外的几乎所有情况。
我们必须确保转换的正确性(手动确认)
int slo = static_cast<int>(3.3);
double dd = static_cast<double>(slo);
可以转换const的pointer,但是注意,只是转换,不能写值。
const char *cp;
char* p = const_cast<char*>(cp); // OK, but cannot write p
char* tp = static_cast<char*>(cp); //error
可以理解为一种重新定义的cast。譬如
int *ip;
char *pc = reinterpret_cast<char*>(ip);
string str(pc); // error, cause pc is not REAL char*
由于这样的转换,编译器不会报错,但是执行时会导致不可逆****神奇的后果,所以一般不推荐使用。
附:
在mscpp中
char的大小是int的4分之1
| Type | Size |
|---|---|
| bool, char, unsigned char, signed char, __int8 | 1 byte |
| __int16, short, unsigned short, wchar_t, __wchar_t | 2 bytes |
| float, __int32, int, unsigned int, long, unsigned long | 4 bytes |
| double, __int64, long double, long long | 8 bytes |
专门转换指针和引用的cast。这里不详细说明。也不推荐使用
它是RTTI(run-time type identification)的一个运算符。它在以下的情况下使用;
struct Mom {
public:
virtual int sub(int a, int b) { return a - b; }
};
struct Son : Mom {
public:
int sub(int a, int b) {
return a + b;
}
virtual int add(int a, int b) {
return a + b;
}
};
int main() {
Mom* m = new Mom;
// failed
if (Son* s = dynamic_cast<Son*>(m)) {
cout << s->add(1, 2) << endl;
}
else {
cout << "failed" << endl;
}
delete m;
m = new Son;
// successed
if (Son* s = dynamic_cast<Son*>(m)) {
cout << s->add(1, 2) << endl;
}
else {
cout << "failed" << endl;
}
return 0;
}
这里并没有详细讨论隐式转换(implicit conversion)