zoukankan      html  css  js  c++  java
  • C++库研究笔记——操作符重载实现类型转换&这样做的意义

    目标:

    已知这个接口:

    std::vector<double> add_vec(double *d1, double *d2)
    {
    .....
    return result;
    }


    我们自定义了这个类:

    class array
    {
    int size_;
    double *data_;
    ....
    };


    要求实现:

    array v1(10), v2(10);
    add_vec(v1, v2);

    留意到,当array 类型传入add_vec时,会遇到(double*) 类型的“试探性”强制转换, 所以,我们只要做一个从array到,(double*)的类型转换即可。


    这样做的好处

    • 1.有了类型转换,我们不需要再写这样一个多态函数实现array 与array的相加
    std::vector<double> add_vec(array d1, array d2)
    {
    .....
    return result;
    }
    


    • 2.以下的接口:
    std::vector<double> add_vec(double* d1, double* d2)

    可能重写起来非常麻烦,甚至add_vec(double*, double*) 是别人封装好的,我们看不到源代码,此时更谈不上重写



    实现方法及测试代码:(直接在这个代码上增加,所以代码有些乱)

    C++类型转换操作符(type conversion operator)

    #include <iostream>
    
     class D {
     public:
        D(double d) : d_(d) {
            data_=new double[10];
            for(int i=0; i<10; i++)
                data_[i]=d;
        }
    
        ~D()    {   delete []data_;   }
    
        /* “(int)D”类型转换 */
        operator int() const {
            std::cout << "(int)d called!" << std::endl;
            return static_cast<int>(d_);
        }
    
        // for: double me=    *d1;      //ok
        double& operator*(void) {
            return *data_;
        }
    
        // for: double *me2= (double*)d1;
        operator double*(void){
            return data_;
        }
    
    
     private:
        double d_;
        double *data_;
    };
    
     int add(int a, int b) {
        return a + b;
    }
    
    #include <vector>
    std::vector<double> add_vec(double* d1, double* d2)
    {
        std::vector<double> r(10);
        for(int i=0; i<10; i++){
            r[i]=d1[i]+d2[i];
        }
            
        return r;
    }
    
    
     int main() {
        D d1 = 1.1;
        D d2 = 2.2;
        std::cout << add(d1, d2) << std::endl;
    
        double me=    *d1;      //ok
        std::cout<<"me:"<<me<<std::endl;
        double *me2= (double*)d1;   // ok
    
        std::vector<double> r;
        r=add_vec(d1, d2);
        for(int i=0; i<r.size(); i++){
            std::cout<<r[i]<<" "<<std::endl;
        }
    
    
        //std::cout << add_vec(d1, d2) << std::endl;
    
        return 0;
    }


    输出:

    (int)d called!
    (int)d called!
    3
    me:1.1
    3.3 
    3.3 
    3.3 
    3.3 
    3.3 
    3.3 
    3.3 
    3.3 
    3.3 
    3.3 

    补充:

    注意到:

        double me=    *d1;     
        double *me= (double*)d1;   

    第二个的意义为把 D类型当成一个指针, 然后把把指针(即地址)赋值给me

    第一个意义为:把D类型先假设指针,然后把指针指向的值转给me

    二者等价,所以,可删除其中一个冗余定义,经过测试,代码仍能正常运行


    
        // for: double *me2= (double*)d1;
        operator double*(void){
            return data_;
        }

    但是如果:

        // for: double me=    *d1;      //ok
        double& operator*(void) {
            return *data_;
        }
    
    

    则会报错:

    Press ENTER or type command to continue
    main.cpp: In function ‘int main()’:
    main.cpp:62:27: error: invalid cast from type ‘D’ to type ‘double*’
    main.cpp:63:18: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
    main.cpp:69:21: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
    main.cpp:44:21: error:   initializing argument 1 of ‘std::vector<double> add_vec(double*, double*)’ [-fpermissive]
    main.cpp:69:21: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
    main.cpp:44:21: error:   initializing argument 2 of ‘std::vector<double> add_vec(double*, double*)’ [-fpermissive]


    仔细理解,编译器这样做是有道理的,因为第一个重载只是第一个的特殊情况,不能包括第一个,而第二个重载却能包含第一个


    更多参见

    Can a cast operator be explicit?

    How do conversion operators work in C++?

  • 相关阅读:
    H5中canvas标签制作在线画板
    H5中标签Canvas实现图像动画
    H5中画图标签Canvas---画矩形,画线,画圆,渐变色,图形载入
    java 的反射机制
    maven的介绍
    000 关于IDEA的基本环境配置以及快速使用(git拉载程序,Jdk安装,tomcat部署,应用程序打包运行)
    H5视频播放器属性与API控件,以及对程序的解释
    HTML5 标签语法变化和使用概念
    H5的简介
    android驱动USB摄像头
  • 原文地址:https://www.cnblogs.com/riskyer/p/3225878.html
Copyright © 2011-2022 走看看