zoukankan      html  css  js  c++  java
  • C++ 操作符重载

    题外话,贴个白噪音网站 Rainy Mood ,敲代码的时候可以听,就像不存在一样

    言归正传

    在C++复制控制那篇帖子里面,有提到操作符的功能实际上都是被定义出来的。--这一点其实可以推广到其他的语言,只不过其他语言禁止了自定义操作符。

    先说个总结认识:操作符本质上是函数,只不过不同于普通函数,标准里单独规定了怎么写怎么调用它。

    前提

      语言底层实现了内置类型的操作符定义,并且,不允许重新自定义内置类型的操作符。

      为了保证内置类型的操作符不被重载,编译器对操作符函数做出了限制---这个稍后再说。

    规定一

      操作符函数都是以operator再加上操作符作为函数名的,如operator+、operator=等等。

      只要正确的定义(重载)了操作符函数,那么相应类型去调用操作符时,本质上就是调用这个操作符函数。--例如复制控制那篇里提到过的赋值操作符重载。

      如:

    #include <iostream>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    class Person{
    private:
        string name;
        int age;
    public:
        Person(string _name="anonymous", int _age=18):name(_name),age(_age){} //带默认实参的构造函数
        Person operator+(const Person &person_b){
            Person person; //default 
            person.name = name + person_b.name; // 
            person.age = age + person_b.age;
            return person;
        }
    
        string toString(){ // 模仿Java的toString()。实际上不必这样,见<<重载。
            ostringstream out;
            out<<"name=["<<name<<"], age=["<<age<<"]";
            return out.str();
        }
    };
    
    int main(){
        Person p1;
        Person p2;
    
        Person p3,p4;
        p3=p1+p2; // operator +
        p4=p1.operator+(p2); //
    
        cout<<"p3:"<<p3.toString()<<endl;
        cout<<"p4:"<<p4.toString()<<endl;
    
        return 0;
    }

      上面,p1+p2 p1.operator+(p2) 是完全一致的,也就是说编译器规定了遇到+就会去调用operator+() 。其他的操作符同理。

    不想打字了,直接上代码吧。

    下面的代码示例了类型转换、调用操作符重载、io流重载。

    有一点需要分清楚:io流重载是输出到流或者从流输入用的,而类型转换却不是。

    这里极其容易将输出流误认为转换成string等---但这不是一回事!!!

    #include <iostream>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    class A{
    private:
        int num;
    public:
        A(int _num=0):num(_num){
            cout<<"构造函数"<<endl;
        }
    
        //输出函数
        virtual void print()const{
            cout<<num<<endl;
        }
        //转成string
        virtual operator string() const{
            cout<<"operator string() called"<<endl;
            ostringstream out;
            out<<num;
            return out.str();
        }
        operator int() const{
            cout<<"operator int() called"<<endl;
            return num;
        }
        // ostream &operator<<(ostream &in) const{ //不能这样写,因为默认第一个操作数是this?会导致a<<cout<<endl;这样的写法
        //     cout<<"operator<< called"<<endl;
        //     return in<<num;
        // }
        
        //调用操作符() 重载--这里用于设置新值
        virtual void operator() (const int &_num){
            cout<<"调用操作符() 重载"<<endl;
            num=_num;
        }
    
    public:
        friend ostream &operator<<(ostream &in, const A &a);
        // friend ostream &operator<<(const A &a ,ostream &in); //会导致a<<cout<<endl;这样的写法
    };
    
    // 为了跟默认的io操作一致,要求形参顺序必须这样!否则就是下面那样,会导致a<<cout<<endl;这样的写法
    ostream &operator<<(ostream &in, const A &a) {
        cout<<"operator<< called"<<endl;
        return in<<a.num;
    }
    
    // 会导致a<<cout<<endl;这样的写法
    // ostream &operator<<( const A &a,ostream &in) {
    //     cout<<"operator<< called"<<endl;
    //     return in<<a.num;
    // }
    
    
    
    int main(int argc, char const *argv[])
    {
        A a;
        a(5);//函数对象
    
        cout << a << endl; //奇怪,为什么之前就可以?operator_overload2.cpp --因为默认没有转成string,而是转成了int
    
        string s(a);
        cout<<s<<endl;
        cout<<"---"<<endl;
        cout<<a<<endl;
        // a<<cout<<endl; // (a<<cout)返回cout, 再cout<<endl;卧槽
    
        return 0;
    }
  • 相关阅读:
    元素设置float属性后,其后面的元素的位置问题
    Vue.js经典开源项目汇总
    ES6-模块导入导出
    JavaScript内存泄漏
    父元素高度比子元素高度多几个像素的解决方法
    jasmine —— Spies(转)
    用npm-run自动化任务(转)
    AngularJS中页面传参方法
    Path模块部分常用函数解析——NodeJS
    html特殊字符表
  • 原文地址:https://www.cnblogs.com/larryzeal/p/5629599.html
Copyright © 2011-2022 走看看