C++表达式

C++表达式

  • 主要是参考C++ primer书籍上的一些内容,加上一些找的其他资料与自己写的代码

重载右键头->

二维数组引用

  • 二维数组中,每个元素都是一个一维数组。但是如果在使用中,直接取其特定的值,会将该值视为指针(指向一个一维数组),而如果采用引用的方式进行使用的话,则会将其视为一维数组,从而可以实现进一步的轮询迭代

  • 代码
    void test()
    {
    int arr[2][3] = {0};
    // 会编译出错,因为将arr中的每个元素视为指针
    //for (auto a : arr)
    // for (auto sa : a)
    // cout << sa << endl;

        // 使用引用的方式,没有问题,因为将arr中的每个元素视为一维数组
        // 引用的方式也避免了因初始化局部变量而造成的开销
        for (auto &a : arr)
            for (auto &sa : a)
                cout << sa << endl;
    
    }
    

除法与求余

  • C++11中,(-m)/n,(m/-n)都被当成了-(m/n)(-m)%n被当成-(m%n)m%(-n)被当成了m%n,(m>0,n>0)
  • 代码

    void test()
    {
        int a = 29;
        int b = 7;
    
        cout << -a % b << endl;
        cout << a % -b << endl;
        cout << -a / b << endl;
        cout << a / -b << endl;
    }
    

指针数组与指向数组的指针

  • 注意:在使用的过程中,如果不清楚操作符的优先级,可以用括号进行强制优先运行,防止误用的情况。
  • 代码

    void test()
    {
        int arr[10] = {0,1,2,3,4,5,6,7,8,9};
        int (*pa)[10] = &arr; //指向一个元素个数为10的数组的指针
        int *pb[10] = {0}; // 一个包含了10个整形指针的数组
        for (int i = 0; i < 10; i++)
            pb[i] = arr + 9 - i;
        for (auto &a : *pa)
            cout << a << " ";
        cout << endl << endl;;
        for (auto &a : pb)
            cout << *a << " ";
        cout << endl;
    }
    

安全的类型转换

显示转换与隐式转换

  • C++中有显示转换与隐式转换,隐式转换是不声明其转换后类型,而是让编译器自动识别其转换类型,而显示转换时手动指定转换类型

上行转换与下行转换

  • 上行转换:沿继承链向上转换(基类的方向),这个与int转换为long long,char转换为int(宽化转换)是等效的
  • 上行转换:沿继承链向下转换(子类的方向),这个与long long转换为int,int转换为char(窄化转换)是等效的

问题

  • 一般的上行转换是没有问题,因为存在精度损失的问题,但是如果进行下行转化,尤其是在基类要转换到子类时,常常会出现问题,因为下行转换时,原来的父类对象中并没有子类的信息,因此需要进行安全转换

C++中的安全转换

  • 有4种:static_cast, dynamic_cast, reinterpret_cast, const_cast

static_cast

  • 最接近C语言中的强制类型转换,按照这种方法,对于无法进行转换的操作,编译器会给出报错(比如说两个没有继承关系的类之间的转换)
  • 代码

    class A{
    protected:
        double i_, j_;
    };
    class B {
    public:
        B(int x, int y) : x_(x), y_(y) {}
        int calc(){ return x_+y_; }
    private:
        int x_, y_;
    };
    void test()
    {
        A a, *pa = 0;
        B b(1,2), *pb = 0;
        pa = (A*)&b;
        pb = (B*)&a; // 不安全的转换,但是不会报错
        // pb = static_cast<B*>(&a); // 这句话会报错
        pb->calc();
    }
    

dynamic_cast

  • 动态转换是在运行时对类型的转换信息进行分析
  • 动态转换的要求:被转换的类一定要包含虚函数以支持多态,否则会编译错误
  • 关于为什么需要有虚函数:为了判断类之间的继承关系,具体可以见:http://www.cnblogs.com/bastard/archive/2011/12/14/2288117.html
  • 如果转换的两个类之间没有直接的继承关系,则会转换失败(编译没有问题),但是转换结果为NULL
  • 代码

    class A{
    public:
        virtual void print(){}
    
    };
    class B {
    public:
        B(int x, int y) : x_(x), y_(y) {}
        int calc(){ return x_+y_; }
    private:
        int x_, y_;
    };
    void test()
    {
        A a, *pa = 0;
        B b(1,2), *pb = 0;
        pa = (A*)&b;
        pb = (B*)&a; // 不安全的转换,但是不会报错
        pb = dynamic_cast<B*>(&a); // 动态转换,被转换的类中必须含有虚函数(多态)
        // 如果转换失败,pb为NULL
        if (pb != NULL)
        {
            pb->calc();
        }
    
    }
    

reinterpret_cast

  • 重解释转换是提到的安全转换中最不安全的一种,因为它可以实现互不相关的两个类之间转换
  • 重解释转换中,转换后类型需要是指针或者引用
    *

const_cast

  • 将常量转换为非常量
  • const_cast也需要转换后的类型是指针、引用或者是指向类成员的指针
  • 代码

    void test()
    {
        const char *c = "abcdefg"; // *c是常量,不可修改,但是c可以修改
        char *cc = const_cast<char*>( c );
        cout << c << endl;
        c = "5666"; // 编译通过
        // c[0] = '7'; // 编译报错
        // *(cc + 1) = 'r';
        // *cc = 'r'; // cc的内容是字符串常量,可以读取,但是无法修改
        cout << *(cc+1) << endl;
        cout << c << endl;
        cout << cc << endl;
    
        char tmp[] = "123344";  // tmp是一个字符数组,编译器会分配一段空间用于存储这些值,因此可以对其进行修改
        tmp[4] = 'r';
        cout << tmp << endl;
    }
    
  • 注意:const_cast只改变变量的常量属性,无法进行不同类型之间的转换

  • 关于上面提到的字符串常量与字符数组的使用区别的解释参考链接:http://www.voidcn.com/article/p-mvewadvn-bbd.html,如果需要修改字符串,则需要使用字符数组的形式进行声明或定义

关于安全转换的主要参考链接:http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html

猜你喜欢

转载自blog.csdn.net/u012526003/article/details/80168505