类型转换
我们知道,类型不同的值相互赋值时,编译器有时候会进行隐式类型的转换,但是隐式类型的转换有时候会有一些坑。
如上图,如果当pos传0时,end先会被隐式转换成size_t类型(无符号int),结果就是程序死循环了。 虽然这个也可以有多种方法来避免,比如给pos进行int强转等等。
在C++中,在父子类对象赋值的时候又是怎么转换的呢?
向上转型
就是将指向子类对象的指针给指向父类对象的指针赋值,也就是我们之前所知道的切片。 这种转型是安全的。
向下转型
与向上转型相反,它是将指向父类对象的指针给子类对象的指针赋值,但是这种转型并不安全,因为此时这个指向父类对象的指针可以调用子类对象特有的成员,因此越界而程序崩溃。
volatile
这个关键字不常用,它的作用是对于被volatile修饰的变量,每次读取的时候都从内存中读取。
如上图,虽然我对a进行了修改,但是我们读取的时候a并不是 从内存中读取的(虽然那块内存已经被修改了),我们是从寄存器中对a进行读取的,那么我们只需要在a前加上volatile关键字就可以让每次a都从内存中读取了。
operator bool operator string
我们知道,对于自定义类型,编译器会进行单参数的隐式类型转换。
那么反过来行不行呢?
很明显不行。这无法进行隐式类型的转换,但是我们可以在A类中重写operator int,这样就可以了
同理,bool 和string都可以这样写。
C++建议规范类型转换
1.static_cast
它使用于两个相近类型的转化,对于两个完全不相关的类型不适用。
int main()
{
double d = 12.34;
int a = static_cast<int>(d);
cout<<a<<endl;
return 0;
}
2.reinterpret_cast
这个和static_cast相反,它适用于两个不相关类型之间的转换。比如一个整形和一个指针类型之间进行转换。
int main()
{
double d = 12.34;
int a = static_cast<int>(d);
cout << a << endl;
// 这里使用static_cast会报错,应该使用reinterpret_cast
//int *p = static_cast<int*>(a);
int *p = reinterpret_cast<int*>(a);
return 0;
}
3.const_cast
它最常用的用途就是去掉const的属性,方便赋值。
void Test ()
{
const int a = 2;
int* p = const_cast< int*>(&a );
*p = 3;
cout<<a <<endl;
}
4.dynamic_cast
这个是专门给C++使用的,它的使用前提必须是父子类并且父类必须有虚函数。
在转换前dynamic_cast会先检查。
对于向上转型,是安全的,那么它会返回子类对象的指针。
对于向下转型,是不安全的,那么它会返回一个空指针。
class A
{
public :
virtual void f(){}
};
class B : public A
{};
void fun (A* pa)
{
// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回
B* pb1 = static_cast<B*>(pa);
B* pb2 = dynamic_cast<B*>(pa);
cout<<"pb1:" <<pb1<< endl;
cout<<"pb2:" <<pb2<< endl;
}
int main ()
{
A a;
B b;
fun(&a);
fun(&b);
return 0;
}
最后还是建议:如果能不用强制类型的转换就不用。
RTTI
C++能通过以下方式支持RTTI: