zoukankan      html  css  js  c++  java
  • C++解析(8):C++中的新成员

    0.目录

    1.动态内存分配

    2.命名空间

    3.强制类型转换

    4.小结

    1.动态内存分配

    1.1 C++中的动态内存分配

    • C++中通过new关键字进行动态内存申请
    • C++中的动态内存申请是基于类型进行的
    • delete关键字用于内存释放

    1.2 new关键字与malloc函数的区别

    • new关键字是C++的一部分
    • malloc是由C库提供的函数
    • new以具体类型为单位进行内存分配
    • malloc以字节为单位进行内存分配
    • new在申请单个类型变量时可进行初始化
    • malloc不具备内存初始化的特性

    1.3 new关键字的初始化

    2.命名空间

    2.1 作用域与命名空间

    在C语言中只有一个全局作用域

    • C语言中所有的全局标识符共享同一个作用域
    • 标识符之间可能发生冲突

    C++中提出了命名空间的概念:

    • 命名空间将全局作用域分成不同的部分
    • 不同命名空间中的标识符可以同名而不会发生冲突
    • 命名空间可以相互嵌套
    • 全局作用域也叫默认命名空间

    2.2 命名空间的定义和使用

    C++命名空间的定义:

    C++命名空间的使用:
    使用整个命名空间:using namespace name;
    使用命名空间中的变量:using name::variable;
    使用默认命名空间中的变量:::variable;

    示例:

    #include <stdio.h>
    
    namespace First
    {
        int i = 0;
    }
    
    namespace Second
    {
        int i = 1;
        
        namespace Internal
        {
            struct P
            {
                int x;
                int y;
            };
        }
    }
    
    int main()
    {
        using namespace First;
        using Second::Internal::P;
        
        printf("First::i = %d
    ", i);
        printf("Second::i = %d
    ", Second::i);
        
        P p = {2, 3};
        
        printf("p.x = %d
    ", p.x);
        printf("p.y = %d
    ", p.y);
        
        return 0;
    }
    

    运行结果:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    First::i = 0
    Second::i = 1
    p.x = 2
    p.y = 3
    

    3.强制类型转换

    3.1 C方式的强制类型转换

    C方式的强制类型转换:

    示例:

    #include <stdio.h>
    
    typedef void(PF)(int);
    
    struct Point
    {
        int x;
        int y;
    };
    
    int main()
    {
        int v = 0x12345;
        PF* pf = (PF*)v;
        char c = char(v);
        Point* p = (Point*)v;
        
        pf(5);
        
        printf("p->x = %d
    ", p->x);
        printf("p->y = %d
    ", p->y);
        
        return 0;
    }
    

    运行结果:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    Segmentation fault (core dumped)
    

    编译器虽然可以编译通过,但是无法运行!

    存在的问题:

    • 过于粗暴——任意类型之间都可以进行转换,编译器很难判断其正确性
    • 难于定位——在源码中无法快速定位所有使用强制类型转换的语句

    问题:强制类型转换在实际工程中是很难完全避免的!如何进行更加安全可靠的转换?

    3.2 C++的新式类型转换

    C++将强制类型转换分为4个不同的类型:

    static_cast强制类型转换——静态类型转换

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

    const_cast强制类型转换

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

    reinterpret_cast强制类型转换

    • 用于指针类型间的强制转换
    • 用于整数指针类型间的强制转换

    dynamic_cast强制类型转换——动态类型转换

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

    示例:

    #include <stdio.h>
    
    void static_cast_demo()
    {
        int i = 0x12345;
        char c = 'c';
        int* pi = &i;
        char* pc = &c;
        
        c = static_cast<char>(i);
        pc = static_cast<char*>(pi); // Error
    }
    
    void const_cast_demo()
    {
        const int& j = 1;
        int& k = const_cast<int&>(j);
        
        const int x = 2;
        int& y = const_cast<int&>(x);
        
        int z = const_cast<int>(x); // Error
        
        k = 5;
        
        printf("k = %d
    ", k);
        printf("j = %d
    ", j);
        
        y = 8;
        
        printf("x = %d
    ", x);
        printf("y = %d
    ", y);
        printf("&x = %p
    ", &x);
        printf("&y = %p
    ", &y);
    }
    
    void reinterpret_cast_demo()
    {
        int i = 0;
        char c = 'c';
        int* pi = &i;
        char* pc = &c;
        
        pc = reinterpret_cast<char*>(pi);
        pi = reinterpret_cast<int*>(pc);
        pi = reinterpret_cast<int*>(i);
        c = reinterpret_cast<char>(i); // Error
    }
    
    void dynamic_cast_demo()
    {
        int i = 0;
        int* pi = &i;
        char* pc = dynamic_cast<char*>(pi); // Error
    }
    
    int main()
    {
        static_cast_demo();
        const_cast_demo();
        reinterpret_cast_demo();
        dynamic_cast_demo();
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    test.cpp: In function ‘void static_cast_demo()’:
    test.cpp:11: error: invalid static_cast from type ‘int*’ to type ‘char*’
    test.cpp: In function ‘void const_cast_demo()’:
    test.cpp:22: error: invalid use of const_cast with type ‘int’, which is not a pointer, reference, nor a pointer-to-data-member type
    test.cpp: In function ‘void reinterpret_cast_demo()’:
    test.cpp:47: error: invalid cast from type ‘int’ to type ‘char’
    test.cpp: In function ‘void dynamic_cast_demo()’:
    test.cpp:54: error: cannot dynamic_cast ‘pi’ (of type ‘int*’) to type ‘char*’ (target is not pointer or reference to class)
    

    将出错的几行代码注释后:

    #include <stdio.h>
    
    void static_cast_demo()
    {
        int i = 0x12345;
        char c = 'c';
        int* pi = &i;
        char* pc = &c;
        
        c = static_cast<char>(i);
        //pc = static_cast<char*>(pi); // Error
    }
    
    void const_cast_demo()
    {
        const int& j = 1;
        int& k = const_cast<int&>(j);
        
        const int x = 2;
        int& y = const_cast<int&>(x);
        
        //int z = const_cast<int>(x); // Error
        
        k = 5;
        
        printf("k = %d
    ", k);
        printf("j = %d
    ", j);
        
        y = 8;
        
        printf("x = %d
    ", x);
        printf("y = %d
    ", y);
        printf("&x = %p
    ", &x);
        printf("&y = %p
    ", &y);
    }
    
    void reinterpret_cast_demo()
    {
        int i = 0;
        char c = 'c';
        int* pi = &i;
        char* pc = &c;
        
        pc = reinterpret_cast<char*>(pi);
        pi = reinterpret_cast<int*>(pc);
        pi = reinterpret_cast<int*>(i);
        //c = reinterpret_cast<char>(i); // Error
    }
    
    void dynamic_cast_demo()
    {
        int i = 0;
        int* pi = &i;
        //char* pc = dynamic_cast<char*>(pi); // Error
    }
    
    int main()
    {
        static_cast_demo();
        const_cast_demo();
        reinterpret_cast_demo();
        dynamic_cast_demo();
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    k = 5
    j = 5
    x = 2
    y = 8
    &x = 0x7ffd5a6a5650
    &y = 0x7ffd5a6a5650
    

    4.小结

    • C++中内置了动态内存分配的专用关键字
    • C++中的动态内存分配可以同时进行初始化
    • C++中的动态内存分配是基于类型进行的
    • C++中命名空间概念用于解决名称冲突问题
    • C方式的强制类型转换
      1. 过于粗暴
      2. 潜在的问题不易被发现
      3. 不易在代码中定位
    • 新式类型转换以C++关键字的方式出现
      1. 编译器能够帮助检查潜在的问题
      2. 非常方便的在代码中定位
      3. 支持动态类型识别( dynamic_cast )
  • 相关阅读:
    document.getElementById("mytxt").style.left=""style.left在IE的FF中注意
    asp.net 用户控件中 使用相对路径的解决方法 图片路径问题(用户控件、图片路径) ,ResolveUrl
    探索 Block (一) (手把手讲解Block 底层实现原理)
    iOS 多线程开发 (概念与API简介)
    iOS 性能小点
    iOS runtime (二)(runtime学习之AutoCoding源码分析)
    探索 NSRunLoop (二)(NSRunLoop 自己动手实现SimpleRunLoop)
    iOS NSNotificationCenter (自己实现一个通知中心XMCNotificationCenter)
    iOS runtime (三)(runtime学习之YYModel源码分析)
    iOS runtime(一)(runtime 分析理解)
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10075088.html
Copyright © 2011-2022 走看看