C++的类型转换
C++类型转换
类型转换机制可以分为:隐式类型转换 和 显示类型转换(强制类型转换)
在C中我们这样做类型转换:
成都创新互联技术团队10余年来致力于为客户提供网站建设、成都网站建设、成都品牌网站建设、营销型网站、搜索引擎SEO优化等服务。经过多年发展,公司拥有经验丰富的技术团队,先后服务、推广了上千多家网站,包括各类中小企业、企事单位、高校等机构单位。
float a=1.023
int b;
b=a; //隐式类型转换
或
b=int(a); //显式类型转换
或
b=(int)a;
C++中的类型转换:
隐式类型转换比较常见,在混合类型表达式中经常发生.比如在表达式中存在short和int,那么就过会发生整型提升.四种强制类型转换操作符:static_cast、dynamic_cast、const_cast、reinterpret_cast。
1、static_cast与dynamic_cast:
前者提供的是编译时期的静态类型检测,后者提供的是运行时检测.
static_cast: 1)完成基础数据类型,2)同一个继承体系中类型的转换 3)任意类型与空指针类型void*之间的转换。
dynamic_cast:使用多态的场景,增加了一层对真实调用对象类型的检查
char c = 65;
int *p = (int *)&c;
cout<<(char)*p<(&c); //编译报错:error: invalid static_cast from type ‘char*’ to type ‘int*’
在上面的例子中,Clike可以运行,然而修改过的*p如果使用,运行结果将会出现错误,而使用static_cast可以将错误在编译时期检查出
在不同继承体系的自定义类型中:
class A
{
public:
A(){}
~A(){}
private:
int i, j;
};
class C
{
public:
C(){}
~C(){}
void printC()
{
std::cout <<"call printC() in class C" <printC(); //"call printC() in class C"
//ptrC = static_cast(ptrA); //编译报错:error: invalid static_cast from type 'A*’ to type C*
上面A C是两个无关的类,然而使用Clike可以实现这种类型的强制转换,这是十分危险的! 使用static_cast可以将这种潜在的危险在编译器找出来.
在同一继承体系中:
upcast(向上转换即子类转成父类):没有问题.因为父类的行为都包含在子类中;
downcast(向下转换):有可能会出现问题,编译时可能不会发现.
一个类的行为和自身的类型相关.也就是一个A类型的指针总会优先调用自己A类内的函数,当然发生继承中的重写(虚继承等)例外.
#include
#include
using namespace std;
class A
{
public:
A():i(1), j(1){}
~A(){}
void printA()
{
std::cout <<"call printA() in class A" < printSum();
A *ptrA = static_cast(ptrB);
ptrA -> printA();
ptrA -> printSum();
//打印结果:sum = 2
//在进行upcast的时候,指针指向的对象的行为与指针的类型相关。
ptrA = new A;
ptrB = static_cast(ptrA);
ptrB -> printB();
ptrB -> printSum();
//打印结果:sum = 0
//在进行downcast的时候,其行为是“undefined”。
B b;
B &rB = b;
rB.printSum();
//打印结果: sum = 4
A &rA = static_cast(b);
rA.printA();
rA.printSum();
//打印结果: sum = 2
//在进行upcast的时候,指针指向的对象的行为与引用类型相关.
A a;
A &rA1 = a;
rA.printSum();
B &rB1 = static_cast(a);
rB1.printB();
//打印结果:sum = 4
rB1.printSum();
//打印结果 :sum = 1.45863e-316
//在进行downcast的时候,其行为是“undefined”。
return 0;
}
这里其实很明显,在downcast转换的时候,会出现一些跟指针或者引用类型相关的函数调用,但是因为指针或者引用(父类)
reinterpret_cast
仅仅是复制n1的比特位到d_r, 没有进行必要的分析.interpret_cast是为了映射到一个完全不同类型\
的意思,这个关键词在我们需要把类型映射回原有类型时用到它。我们映射到的类型仅仅是为了故弄\
玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话
const_cast
去除const常量属性,使其可以修改volatile属性的转换 易变类型<->不同类型.
#include
#include
#include
using namespace std;
class A {
public:
A(){};
int m_a;
};
class B {
public:
int m_b;
};
class C : public A, public B {};
int main()
{
const A a;
//a.num = 1;
const_cast(a).m_a = 2;
//a.num = 3;编译不能通过,说明const_cast只能转换一次,不是永久脱离原有const属性
cout<(n);
double d_r = reinterpret_cast(n);
cout<
#include
#include
#include
using namespace std;
class A{
public:
virtual void foo(){
cout<<"A foo"<
//虚函数的出现会带来动态机制 Class A 至少要有一个虚函数
void pp(){
cout<<"A pp"<
};
class B: public A{
public:
void foo(){
cout<<"B foo"<
void pp(){
cout<<"B PP"<
void functionB(){
cout<<"Excute FunctionB!"<
};
int main()
{
B b;
A pa = &b;
pa->foo();
pa->pp();
//基类指针可以指向派生类,但是只能调用基类和派生类都存在的成员,也就是说不能调用派生类中新增的成员!
//pa->FunctionB();//error: 'class A' has no member named 'FunctionB'
if(dynamic_cast>(pa) == NULL){
cout<<"NULL"<
cout<
dynamic_cast>(pa)->pp();
dynamic_cast>(pa)->functionB();
}
A aa;
//B pb = &aa;派生类不能指向基类
B pbNull = NULL;
pbNull->functionB();//fine
pbNull->pp();//fine
//pbNull->functionB(); crash!foo调用了虚函数,编译器需要根据对象的虚函数指针查找虚函数表,但为空,crash!
return 0;
}
当前名称:C++的类型转换
标题URL:http://myzitong.com/article/jehgij.html