当前位置:   article > 正文

C++的强制类型转换_c++强制类型转换规则

c++强制类型转换规则

C++因为兼容C的特性,对于C中的强制类型转换也是可以利用的

先来叙述强制类型转换的全过程

数据类型排名(从高到低):long double,double,float,unsigned long long int,long long int,unsigned long int,long int,unsigned int,int

有两个规则要注明:

/*
规则 1:char、short 和 unsigned short 值自动升级为 int 值。细心的读者可能已经注意到,char、short 和 unsigned short 都未出现在表 1 中,这是因为无论何时在数学表达式中使用这些数据类型的值,它们都将自动升级为 int 类型。

规则 2:当运算符使用不同数据类型的两个值时,较低排名的值将被升级为较高排名值的类型。

规则 3:当表达式的最终值分配给变量时,它将被转换为该变量的数据类型。

规则 4:当变量值的数据类型更改时,它不会影响变量本身
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其次来说明一下C的强制类型转换
说明:C的强制类型转换是把变量从一种类型转换为另一种数据类型

// (type_name) expression
// type_name (expression)
#include <stdio.h>

main() {
   int sum = 17, count = 5;
   double mean;

   mean = (double) sum / count;
   printf("Value of mean : %f\n", mean );
}
// output:Value of mean : 3.400000
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

隐式转换

#include <stdio.h>

main() {
   int  i = 17;
   char c = 'c'; /* ascii 值是 99 */
   int sum;

   sum = i + c;
   printf("Value of sum : %d\n", sum );
}
// output:Value of sum : 116
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

最后来说说C++的强制类型转换

//静态转换
static_cast<new_type> (expression)
//动态转换
dynamic_cast<new_type> (expression) 
//常量转换
const_cast<new_type> (expression) 
//重新解释转换
reinterpret_cast<new_type> (expression)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

static_cast 静态转换

static_cast静态转换相当于C语言中的强制转换,但不能实现普通指针数据(空指针除外)的强制转换,一般用于父类和子类指针、引用间的相互转换。

①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。不管是否发生多态,父子之间互转时,编译器都不会报错。

进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;

进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的,但是编译器不会报错。

②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

③把空指针转换成目标类型的空指针。

④把任何指针类型转换成空指针类型。

⑤可以对普通数据的const和non_const进行转换,但不能对普通数据取地址后的指针进行const添加和消去。

⑥无继承关系的自定义类型,不可转换,不支持类间交叉转换。

注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性

class Person{

};

class Son :public Person{

};

class My{};

void test02(){
    char a = 'c';
    int b = static_cast<int> (a);
    cout << b << endl;

    const char a0 = 'c';
    char b0 = static_cast<char> (a0);
    cout << b0 << endl;

    char a1 = 'c';
    const char b1 = static_cast<const char> (a1);
    cout << b1 << endl;

    //static无法丢掉常量或其他类型限定符,只限于对常量地址的指针去const
    //const char a2 = 'c';
    //char *b2 = static_cast<char*> (&a2);
    //cout << b2 << endl;


    //父类指针转为子类
    Person *p = NULL;
    Son *s = static_cast<Son*>(p);

    //子类指针转为父类
    Son *s0 = NULL;
    Person *p0 = static_cast<Person*>(s0);

    //My* my= static_cast<My*>(p); 无继承关系的自定义数据类型不能相互转换

    //父类对象无法转为子类对象
    //Person p1;
    //Son s1 = static_cast<Son>(p1);

    //子类对象可以赋值,初始化父类对象
    Son s2;
    Person p2 = static_cast<Person>(s2);

    //父类引用转为子类
    Person p_ ;
    Person &p3 = p_;
    Son &s3 = static_cast<Son&>(p3);

    //子类引用转为父类
    Son s_;
    Son &s4 = s_;
    Person &p4 = static_cast<Person&>(s4);

    //空指针转化为目标类型的指针
    void *pPtr = NULL;
    int *iPtr = static_cast<int*>(pPtr);

    //任何指针转化为空指针类型
    int *aInt = NULL;
    void *aVoid = static_cast<void*>(aInt);

    //static_cast不能进行出void外的指针强制互转
    char *tmp = "abc";
    cout << tmp << endl;

    //cout << static_cast<int*>(tmp) << endl;不能将char*型的数据转换为int*,但C语言强转可以
    cout << static_cast<void*>(tmp) << endl;

    int *tmp_ = (int*)(tmp);
    cout << static_cast<int*>(tmp_) << endl;

    int *tmpInt = 0;
    cout << tmpInt << endl;
    cout << static_cast<void*>(tmpInt) << endl;
    cout << static_cast<int*>(tmpInt) << endl;//转为自身可以
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

dynamic_cast 动态转换

动态转换的类型和操作数必须是完整类类型或空指针、空引用,说人话就是说,只能用于类间转换,支持类间交叉转换,不能操作普通数据。

主要用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换,

①进行上行转换(把派生类的指针或引用转换成基类表示)是安全的,允许转换;

②进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的,不允许转化,编译器会报错;

③发生多态时,允许互相转换。

④无继承关系的类之间也可以相互转换,类之间的交叉转换。

⑤如果dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常

const_cast 常量转换

const_cast,用于修改类型的const或volatile属性,不能对非指针或非引用的变量添加或移除const。

const int g = 20;
//int h = const_cast<int>(g); //不允许对普通数据进行操作
int *h = const_cast<int*>(&g);//去掉const常量const属性

const int g0 = 20;
const int &g2 = g0;
int &h = const_cast<int &>(g0);//去掉const引用const属性
int &h2 = const_cast<int &>(g2);//去掉const引用const属性

const char *g1 = "hello";
char *h = const_cast<char *>(g1);//去掉const指针const属性
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

reinterpret_cast 重新解释转换

最鸡肋的转换函数,可以将任意类型转换为任意类型,因此非常不安全。只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。

static_cast和reinterpret_cast的区别主要在于多重继承
前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节(可查看virtual虚函数博客详述),这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/222930
推荐阅读
相关标签
  

闽ICP备14008679号