新型的类型转换(九)-创新互联

   我们之前在 C 语言进行类型转换是强制类型转换的,这样极易出 bug,还不易查找。格式如下:(Type)(Experssion) 或 Type(Experssion),我们来看个示例代码,看看 C 语言中的强制类型转换

为东城等地区用户提供了全套网页设计制作服务,及东城网站建设行业解决方案。主营业务为网站制作、成都网站建设、东城网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
#include 

typedef void(PF)(int);

struct Point
{
    int x;
    int y;
};

int main(int argc, char *argv[])
{
    int v = 0x12345;
    PF* pf = (PF*)v;
    char c = char(v);
    Point* p = (Point*)v;
    
    pf(5);
    
    printf("p->x = %d\n", p->x);
    printf("p->y = %d\n", p->y);
    
    return 0;
}

        编译结果如下

新型的类型转换(九)

        我们看到直接运行段错误,但是它编译是通过的,因此我们如果在大型的项目中是难以查找 bug 的。

        在 C 方式的强制类型转换的过程中,它存在的问题:a> 过于粗暴:任意类型之间都可以进行转换,编译器很难判断其正确性;b> 难于定位:在源码中无法快速定位所有使用强制类型转换的语句。那么强制类型转换在实际工程中是很难完全避免的!如何进行更加安全可靠的转换呢?在 C++ 中出现了新式类型转换,C++ 将强制类型转换分为 4 中不同的类型:a> static_cast;b> const_cast;c> dynamic_cast;d> reinterpret_cast;用法是:xxx_cast(Expression)。下来我们分别来讲下这四种新式类型转换的特点及要求

        A、static_cast 强制类型转换

        用于基本类型间的转换;不能用于基本类型指针间的转换;用于有继承关系类对象之间的转换和类指针之间的转换。

        B、const_cast 强制类型转换

        用于去除变量的只读属性;强制转换的目标类型必须是指针或引用。

        C、reinterpret_cast 强制类型转换

        用于指针类型间的强制转换;用于整数和指针类型间的强制转换。

        D、dynamic_cast 强制类型转换

        用于有继承关系的类指针间的转换;用于有交叉关系的类指针间的转换;具有类型检查的功能;需要虚函数的支持。

        关于上面讲到的有些概念,我们会在后面进行详细的介绍,下来我们以代码为例进行分析

#include 

void static_cast_demo()
{
    int i = 0x12345;
    char c = 'c';
    int* pi = &i;
    char* pc = &c;
    
    c = static_cast(i);
    pc = static_cast(pi);    // error
}

void const_cast_demo()
{
    const int& j = 1;
    int& k = const_cast(j);
    
    const int x = 2;
    int& y = const_cast(x);
    
    int z = const_cast(x);    // error
    
    k = 5;
    
    printf("k = %d\n", k);
    printf("j = %d\n", j);
    
    y = 8;
    
    printf("x = %d\n", x);
    printf("y = %d\n", y);
    printf("&x = %p\n", &x);
    printf("&y = %p\n", &y);
}

void reinterpret_cast_demo()
{
    int i = 0;
    char c = 'c';
    int* pi = &i;
    char* pc = &c;
    
    pc = reinterpret_cast(pi);
    pi = reinterpret_cast(pc);
    pi = reinterpret_cast(i);
    c = reinterpret_cast(i);     // error
}

void dynamic_cast_demo()
{
    int i = 0;
    int* pi = &i;
    char* pc = dynamic_cast(pi);    // error
}

int main()
{
    static_cast_demo();
    const_cast_demo();
    reinterpret_cast_demo();
    dynamic_cast_demo();
    
    return 0;
}

        我们来分析下这个代码,在 static_cast_demo 中,static_cast 不能用于指针间的转换,所以第 11 行会报错。在 const_cast_demo 中,第 16 行定义了一个具有只读属性的变量 j,我们还是可以通过 const_cast 来改变它的属性的。第 19 行定义了一个真正意义上的常量,它会进入到符号表中,但在栈上会为它分配 4 个字节的空间,所以第 20 行的也会成功。const_cast 强制转换的目标类型必须是指针或引用,所以第 22 行会报错。第 26 、 27 行会打印出 5、5;第 31 - 34 会打印出 2、8、后面两个地址是一样的。在 reinterpret_cast_demo 中,reinterpret_cast 用于指针类型间及整数和指针类型间的强制转换,所以第 47 行会报错。在 dynamic_cast_demo 中,第 54 行会报错。我们来看看编译结果

新型的类型转换(九)

        我们分别注释掉这几行,再来编译,看看结果是否如我们所分析的那样

新型的类型转换(九)

        我们看到和我们所分析的是一致的。通过对强制类型转换的学习,总结如下:1、C 方式的强制类型转换:a> 过于粗暴。 b> 潜在的问题不易被发现。 c> 不易在代码中定位;2、新式类型转换以 C++ 关键字的方式出现:a> 编译器能帮助检查潜在的问题。 b> 非常方便的在代码中定位。 c> 支持动态类型识别(dynamic_cast)。

        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享文章:新型的类型转换(九)-创新互联
网页地址:http://myzitong.com/article/ppisp.html