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 )
  • 相关阅读:
    关于ashx的基本应用
    sqlserver中在存储过程中写事务
    安装 SQL Server 2008 需要 Windows PowerShell
    Visual Studio .NET 无法创建或打开应用程序。问题很可能是因为本地WEB本地服务器上没有安装所需的组件。
    Android开发之旅:环境搭建及HelloWorld
    sqlserver 2005 两个表之间的更新操作。
    MS SQLSERVER SELECT FOR XML 中字符的限制问题
    把SVN设置成系统服务
    vs2005 水晶报表部署时处理方法
    Expression Studio简体中文正式版 AND KEY
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10075088.html
Copyright © 2011-2022 走看看