9. c++类型转换
c仅支持强制类型转换(cast),TYPE a = (TYPE)a;
c++支持4种风格的类型转换操作符:
static_cast
,编译器认可;reinterpret_cast
,重新解释类型,相当于强制转换,编译器不认可;dynamic_cast
,如子类和父类之间的多态类型转换,不建议;const_cast
,即转换常量属性,不建议。
前两个合起来相当于c的强制类型转换。
格式举例:int a = static_cast<int>(b);
我们应尽量避免使用类型转换。
static_cast
实现基本数据类型之间的转换,如int
转换为char
,编译器会做类型检查。
int a = 3.14
这样的c风格隐式转换会出现warning;int a = static_cast<int>(3.14)
则不会。
凡是可以隐式转换的地方都可以用static_cast
但是,静态转换不支持不同类型指针之间的转换,如int*
到char *
。reinterpret_cast
则支持。
reinterpret_cast
可以转化任何内置的数据类型为其他任何的数据类型,不到万不得已绝对不要用。
dynamic_cast
可以运行时进行类型检查,其他三种都是编译时完成的。
如果转换时非父子关系,则返回nullptr。
使用时,基类中一定要有虚函数。
#include<iostream>
using namespace std;
class Person
{
public:
virtual void come() = 0;
};
class Worker : public Person
{
public:
virtual void come()
{
cout<<"clock in."<<endl;
}
void work()
{
cout<<"work."<<endl;
}
};
class Boss : public Person
{
public:
virtual void come()
{
cout<<"check."<<endl;
}
void rest()
{
cout<<"rest."<<endl;
}
};
void func(Person *p)
{
p->come();
Worker * pworker = dynamic_cast<Worker *>(p);
if(pworker != NULL)
{
pworker->work();
}
Boss * pboss = dynamic_cast<Boss *>(p);
if(pboss != NULL)
{
pboss->rest();
}
}
int main(int argc, char *argv[])
{
Worker worker;
Boss boss;
func(&worker);
func(&boss);
cin.get();
return 0;
}
/*
clock in.
work.
check.
rest.
*/
upcast时,dynamic_cast
和static_cast
的效果是一样的;
downcast时,dynamic_cast
具有类型检查的功能,比static_cast
更安全。转换成功则返回指向类的指针或引用,失败则返回NULL。
Person *pp = static_cast<Person*>(&boss);
不建议使用,除非是单元测试, 如果你需要在运行时确定类型信息, 说明有设计缺陷。
const_cast
它可以使一个本来不是const
类型的数据转换成const
类型的,或者把const
属性去掉。
只读转换为可写时,要确保这块内存可写。
#include<iostream>
using namespace std;
void func(const char *s)
{
char *p = const_cast<char*>(s);
p[0] = 'A';
}
int main(int argc, char *argv[])
{
char s[] = "abc";
//char *s = "abc";
func(s);
printf("%s\n",s);
cin.get();
return 0;
}
对于int这种变量,需要对它的地址(指针)强转,间接修改变量值。