C++强制类型转换
void Test()
{
int i = 1;
//隐式类型转换
double d = i;
printf("%d %.2f\n",i, d);
int* p = &i;
//显示类型转换
int address = (int)p;
printf("%x, %d\n", p, address);
}
static_cast
static_cast用于非多态类型的转换(静态转换),任何标准转换都可以用它,但是不可以用于两个不相关的类型进行转换。
void Test()
{
int i = 1;
double d = static_cast<double>(i);
printf("%d %.2f\n",i, d);
}
reinterpret_cast
reinterpret_cast用于将一种类型转换为不同的类型。
typedef void (*Func)();
int Dosomething(int i)
{
cout<<"Dosomething"<<endl;
return 1;
}
void Test()
{
Func f = reinterpret_cast<Func>(Dosomething);
f();
}
reinterpret_cast( )
T 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。
reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它。我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话)
reinterpret_cast和static_cast的主要区别在多重继承。例如:
class A
{
int m_a;
};
class B
{
int m_b;
};
class C : public A, public B
{};
int main()
{
C c;
printf("%p %p %p\n", &c, reinterpret_cast<B*>(&c), static_cast<B*>(&c));
system("pause");
}
上面这段代码中, 前两个输出值相同,第三个偏移了四个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),reinterpret_cast却不会做这一层转换。
慎用reinterpret_cast
const_cast
const_cast最常用的属性就是删除变量的const属性,方便赋值。
int main()
{
volatile const int a = 2;
//volatile避免值被编译器优化到寄存器
int* p = const_cast<int*>(&a);
*p = 3;
cout<<a<<endl;
system("pause");
}
dynamic_cast
dynamic_cast用于将一个父类对象的指针转换为子类对象的指针或引用(动态转换)
- dynamic_cast只能用于含有虚类的函数
- dynamic_cast会先检查是否能成功转换,能转换则转换,如果不能则返回。
class A
{
public:
virtual void Func(){}
};
class B : A
{};
void fun(A* pa)
{
//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);
system("pause");
return 0;
}
explicit关键字
explicit关键字阻止经过转换构造函数进行的隐式转换的发生。
class A
{
explicit A(int a)
{
cout<<"A(int a)"<<endl;
}
A(const A& a)
{
cout<<"const A& a"<<endl;
}
private:
int _a;
};
int main()
{
A a1(1);
A tmp(1);
A a2(tmp);
A a2 = 1;
}