zoukankan      html  css  js  c++  java
  • C++ 运算符重载

    运算符重载:
         C++中内置的一些运算符只能用于对某些基本类型的变量或常量进行运算,无法用于对象之间的
      运算。有时我们希望能够将这些运算符运用到对象中,使得程序更加简洁易懂。而C++提供的运
      算符重载机制,赋予运算符新的功能,用以解决这些的问题。
      
      运算符重载的实质是编写以运算符作为名称的函数。其定义格式为:
          返回值类型 operator运算符(参数表){
              ......
          }
      包含被重载的运算符的表达式会被编译成对运算符函数的调用,运算符的操作数成为函数调用时
      的实参,运算的结果就是函数的返回值。运算符可以被多次重载,且可以被重载成成员函数或全
      局函数都可以。
      
      运算符重载为全局函数时,参数的个数等于运算符操作数的个数;运算符重载为成员函数时,参
      数个数等于运算符操作数的个数减一。
      
     运算符重载时的一般原则:
         赋值= 下标[] 调用() 和成员访问箭头->等操作符必须定义为成员,将这些操作符定义为非成员
      函数将在编译时标记为错误。
      像赋值一样,复合操作符通常应定义为类的成员。与赋值不同的是,不一定必须这么做,如果定
      义非成员复合赋值操作符,不会出现错误。
      改变对象状态或与给定类型紧密联系的其他一些操作符,如自增、自减和解引用,通常应定义为
      类成员。
      兑成的操作符,如算术运算符、相等运算符、关系运算符和位操作符,最好定义为普通的非成员
      函数。

    #include <iostream>
    
    using namespace std;
    
    class Complex{
        public:
            double real, imag;
            Complex(double r = 0.0,  double i = 0.0):real(r), imag(i){
            }
            Complex operator-(const Complex &c);   // 重载为成员函数 
    }; 
    
    Complex operator+(const Complex &a, const Complex &b){     // 重载为全局函数 
        return Complex(a.real + b.real, a.imag + b.imag);      // 返回一个临时对象 
    }
    
    Complex Complex::operator-(const Complex &c){
        return Complex(real - c.real, imag - c.imag);          // 返回一个临时对象 
    }
    
    int main()
    {
        Complex a(4, 4), b(1, 1), c;
        c = a + b;    // 等效于 c = operator+(a + b); 
        cout << c.real << " , " << c.imag << endl;
        cout << (a-b).real << " , " << (a-b).imag << endl;
        
        return 0;
    }

     重载赋值运算符 "="
         赋值运算要求左右两个操作数的类型至少是匹配的,或者至少是兼容的。
      C++规定赋值运算符"="只能重载为成员函数。
      在对运算符进行重载时,好的风格应该尽量保留运算符原本的特性。

    #include <iostream>
    
    using namespace std;
    
    class CCar{
        public:
            int price;
            CCar(void){
                price = 0;
            }
            CCar(int p):price(p){ }
            CCar &operator=(const CCar * car);
    }; 
    
    CCar & CCar::operator=(const CCar * car){
                price = car->price;
                
                return *this;
            } 
    
    int main()
    {
        CCar c1(10), c2;
        c2 = c1;
        cout << c1.price << " , " << c2.price << endl;
        
        return 0;
    }

    浅拷贝和深拷贝:
         同类对象之间可以通过赋值运算符"="互相赋值。如果没有经过重载,"="的作用就是把左边的
      对象的每个成员变量都变得和右边的对象相等,即执行逐个字节拷贝的工作,这种拷贝叫做浅
      拷贝。有的时候两个对象相等,从实际应用的含义上讲,指的并不应该是两个对象的每个字节
      都相同,而是有其它解释,这时就需要对"="进行重载。

    string s1, s2;
    s1 = "This";
    s2 = "That";
    s2 = s1;    // 使得s2.str和s1.str指向同一个地址,执行的时浅拷贝,导致s2.str原先指向的内存区域无法释放
    
    // 为了解决这些问题,我们需要对"="进行重载。
    
    String & String::operator=(const String &s){
        if(str == s.str)
            return *this;
        if(str)
            delete [] str;
        if(s.str){
            str = new char[strlen(s.str) + 1];
            strcpy(str, s.str);
        }
        else
            str = NULL; 
            
        return *this;
    } 

    运算符重载为友元函数:
         一般来说,将运算符重载为成员函数是一个好的选择,但有时,重载为成员函数无法满足需
      求,就需要重载为全局函数,但作为成员函数无法访问对象的私有成员,因此,这是就需要
      将其重载为友元。

    class Complex{
        private:
            double real;
            double imag;
        public:
            Complex(double r = 0.0, double i = 0.0):real(r), imag(i){ }
            Complex(const Complex &c){
                real = c.real;
                imag = c.imag;
            }
            //  重载加法运算符 
            friend Complex operator+(const Complex &c1, const Complex &c2);
            // 重载减法运算符
            friend Complex operator-(const Complex &c1, const Complex &c2); 
            // 一般在定义算术操作符的同时会定义复合赋值操作符,且复合赋值操作符是由算术操作符实现 
            // 复合赋值操作符 
            Complex &operator+=(const Complex &c2);
            Complex &operator-=(const Complex &c2);
            // 重载流插入运算符和流提取运算符
            friend std::istream& operator>>(std::istream& is, Complex &c); 
            friend std::ostream& operator<<(std::ostream& os, const Complex &c);
            // 自增自减运算符,分为前置和后置形式,一般后置形式通过接受一个额外的int型形参,编译器提供0作为这个形参
            Complex &operator++();
            Complex &operator--();    
            Complex operator++(int i);
            Complex operator--(int i);             
    }; 
    
    Complex operator+(const Complex &c1, const Complex &c2){
        return Complex(c1.real + c2.real, c1.imag + c2.imag);
    }
    
    Complex operator-(const Complex &c1, const Complex &c2){
        return Complex(c1.real - c2.real, c1.imag - c2.imag);
    }
    
    Complex & Complex::operator+=(const Complex &c2){
        Complex c;
        c = *this + c2;
        *this = c;
        return *this;
    }
    
    Complex & Complex::operator-=(const Complex &c2){
        Complex c;
        c = *this - c2;
        *this = c;
        return *this;
    }
    
    std::istream& operator>>(std::istream& is, Complex &c){
        is >> c.real >> c.imag;
        // 错误处理机制 ...... 
        return is;
    }
    
    std::ostream& operator<<(std::ostream& os, const Complex &c){
        os << c.real << " , " << c.imag << endl; 
        return os;
    }
    
    Complex & Complex::operator++(){
        // 错误处理......
        ++real;
        ++imag;
        return *this; 
    }
    
    Complex & Complex::operator--(){
        // 错误处理......
        --real;
        --imag;
        return *this; 
    }
    
    Complex Complex::operator++(int i){
        Complex c(*this);
        ++*this;
        return c;
    }
    
    Complex Complex::operator--(int i){
        Complex c(*this);
        --*this;
        return c;
    }
  • 相关阅读:
    WM_PAINT消息详解,使用InvalidateRect或InvalidateRgn函数刻意产生WM_PAINT消息(WIN7里有变化,“调整视觉效果”,将“启用桌面组合”去掉)
    delphi 大文件的读写 使用 MapviewOffile
    Delphi的子类化控件消息, 消息子类化
    wParam与lParam的区别
    为什么使用DLL
    大数据分包算法
    JSON如何序列图片
    AngularJs学习
    设计模式解读
    js模块化编程总结
  • 原文地址:https://www.cnblogs.com/lnlin/p/7599413.html
Copyright © 2011-2022 走看看