C中的强制转换
在C语言中的强制转换为如下面所示:
short b=1;
int a=(int)b;
int a=int(b);
//******************************************
// class type-casting
#include <iostream>
using namespace std;
class CDummy {
float i,j;
CDummy():i(100),j(10){}
};
class CAddition:public CDummy
{
int *x,y;
public:
CAddition (int a, int b) { x=&a; y=b; }
int result() { return *x+y;}
};
int main () {
CDummy d;
CAddition * padd;
padd = (CAddition*) &d;
cout << padd->result();
return 0;
}
第一个是强制类型的数字类型转换,当小范围向大范围转换是可以隐式的转换,如果是大范围向小范围转换就需要强制类型转换会有waring。就需要前面的两种方式。同样的,如果是类的话,可以将指向子类的指针,指向父类的对象,将父类的对象强制转换为子类的指针。但是这样的话,可能会出现问题,就是实际并不能调用子类的函数等。如果是指向父类的指针指向将子类的对象,是没有问题的。
这个时候C语言中的强制类型转换并没有做出任何的安全提示。
C++中提供了四种强制类型转换的方式
- const_casr<new_type>(expression)
- static_cast <new_type> (expression)
- reinterpret_cast <new_type> (expression)
- dynamic_cast <new_type> (expression)
下面一个个的简单的将一下,我也可看到别人的文章的。
const_casr<new_type>(expression)
第一是,将常量的的类型转换为非常量的。详情可以看:https://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html
const int constant = 21;
const int* const_p = &constant;
int* modifier = const_cast<int*>(&constant);
虽然,这个三个的变量的地址或者是指针指向的地址是一样,但是其实你如果修改了modifier指向的值的话,constant的值其实还是没呀改变的。这中行为是一种未定义的行为。是不推荐的使用的,这种常量转换的应用场合是:第一个,就是我们需要使用一个函数,这个函数的参数变量是非常量的,但是实际上我们传入的参数是常量的,这个时候就需要进行类型转换。转换为非常量的。或者说一个const的对象要调用一个非const的方法,所以需要进行类型转换。
#include <iostream>
using namespace std;
void Printer (int* val,string seperator = "\n")
{
cout << val<< seperator;
}
int main(void)
{
const int consatant = 20;
//Printer(consatant);//Error: invalid conversion from 'int' to 'int*'
Printer(const_cast<int *>(&consatant));
return 0;
}
第二种就是, 用一个const的类型的数据,对一个变量进行了赋值或者是初始化,我们要修改,就可以用类型转换
#include <iostream>
using namespace std;
int main(void) {
int variable = 21;
int* const_p = &variable;
int* modifier = const_cast<int*>(const_p);
*modifier = 7
cout << "variable:" << variable << endl;
return 0;
}
static_cast <new_type> (expression)
这个基本上是和C的强制类型转换,一样是,是可以将两个不同的类型的指针进行强制转换,甚至是可以不讲道理
// class type-casting
#include <iostream>
using namespace std;
class CDummy {
float i,j;
};
class CAddition {
int x,y;
public:
CAddition (int a, int b) { x=a; y=b; }
int result() { return x+y;}
};
int main () {
CDummy d;
CAddition * padd;
padd = (CAddition*) &d;
cout << padd->result();
return 0;
}
比如说这个,两个不同的类型的指针都可以强制转换,不讲道理。
reinterpret_cast <new_type> (expression)
这个更加的不讲道理,也是任何两个类型之间的都可以强行转换,更加不讲道理的是,这个还可以将整数的类型转换为指针,或者是将指针转换为整数的类型。非常的底层很硬核,简直是丧心病狂。
class A {};
A * a = new A;
int B = reinterpret_cast<B*>(a);//correct!
dynamic_cast <new_type> (expression)
动态转换确保类指针的转换是合适完整的,它有两个重要的约束条件,其一是要求new_type为指针或引用,其二是下行转换时要求基类是多态的(基类中包含至少一个虚函数)。
所谓的下行转换。“下”表示沿着继承链向下走(向子类的方向走)。
类似地,上行转换的“上”表示沿继承链向上走(向父类的方向走)。
我们给出结论,上行转换一般是安全的,下行转换很可能是不安全的。
为什么呢?因为子类中包含父类,所以上行转换(只能调用父类的方法,引用父类的成员变量)一般是安全的。但父类中却没有子类的任何信息,而下行转换会调用到子类的方法、引用子类的成员变量,这些父类都没有,所以很容易“指鹿为马”或者干脆指向不存在的内存空间。
#include <iostream>
using namespace std;
class CBase { };
class CDerived: public CBase {};
int main()
{
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived
}
比如这样的转换就是,不可以的,因为子类不是多态的。
#include <iostream>
using namespace std;
class CBase { virtual void dummy() {} };
class CDerived: public CBase {};
int main()
{
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // ok
}
这个编译是没有问题,但是pd的值会是零。也就是说不安全的下行转换,并不会抛出异常,只是将返回的值修改为0.。
一个特例是void *的指针,总是被认为是安全的,但是要必须是多态的。
#include <iostream>
using namespace std;
class A {virtual void f(){}};
class B {virtual void f(){}};
int main() {
A* pa = new A;
B* pb = new B;
void* pv = dynamic_cast<void*>(pa);
cout << pv << endl;
// pv now points to an object of type A
pv = dynamic_cast<void*>(pb);
cout << pv << endl;
// pv now points to an object of type B
}
这个参考的文章是:https://blog.csdn.net/chenlycly/article/details/38713981