C++之运算符重载(下)

4.提高

1.运算符重载机制
编译器实现运算符重载实际上就是通过函数重载实现的,可分为全局函数方式,也可分为成员函数方式进行重载,并没有改变原操作符的属性和语义。只是针对某个特定类定义一种新的数据类型操作。
2.重载赋值运算符


  • 赋值运算符重载用于对象数据的复制
  • operator= 必须重载为成员函数
  • 重载函数原型为:
    类型 & 类名 :: operator= ( const 类名 & ) ;

结论:
1 先释放旧的内存
2 返回一个引用
3 =操作符 从右向左
#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
using namespace std;

//

class  Name
{
public:
    Name(const char *myp)
    {
        m_len = strlen(myp);
        m_p =(char *) malloc(m_len + 1); //
        strcpy(m_p, myp);
    }

    //Name obj2 = obj1;
    //解决方案: 手工的编写拷贝构造函数 使用深copy
    Name(const Name& obj1)
    {
        m_len = obj1.m_len;
        m_p = (char *)malloc(m_len + 1);
        strcpy(m_p, obj1.m_p);
    }

    //obj3 = obj1;  // C++编译器提供的 等号操作 也属 浅拷贝
    //obj3.operator=(obj1)

    Name& operator=(Name &obj1)
    {
        //先释放旧的内存
        if (this->m_p != NULL)
        {
            delete[] m_p;
            m_len = 0;
        }
        //2 根据obj1分配内存大小
        this->m_len = obj1.m_len;
        this->m_p = new char [m_len+1];

        //把obj1赋值
        strcpy(m_p, obj1.m_p);
        return *this;
    }

    ~Name()
    {
        if (m_p != NULL)
        {
            free(m_p);
            m_p = NULL;
            m_len = 0;
        }
    }
protected:
private:
    char *m_p ;
    int m_len; 
};

//对象析构的时候 出现coredump
void objplaymain()
{
    Name obj1("abcdefg");
    Name obj2 = obj1;  //C++编译器提供的 默认的copy构造函数  浅拷贝
    Name obj3("obj3");

    obj3 = obj1;  // C++编译器提供的 等号操作 也属 浅拷贝
    //obj3.operator=(obj1)
    //operato=(Name &obj1)

    obj1 = obj2 = obj3;
    //obj2.operator=(obj3);
    //obj1 = void;
}

void main()
{
    objplaymain();
    cout<<"hello..."<<endl;
    system("pause");
    return ;
}

3.重载下标运算符

  • [ ]运算符用于访问数据对象的元素
  • 重载格式 类型 类 :: operator[] ( 类型 ) ;
  • 只能用成员函数重载,不能用友元函数重载

示例:
设 x 是类 X 的一个对象,则表达式
x [ y ]
可被解释为
x . operator [ ] ( y )
这里写图片描述
这里写图片描述

函数返回值当左值需要返回一个引用!

4.带下标和相等操作符的数组类

  • 类的头文件
#ifndef NEWARRAY_H
#define NEWARRAY_H
#include <iostream>
#include <stdlib.h>

class NewArray
{
public:
    NewArray();
    NewArray(int _len);
    NewArray(const NewArray & obj);
    ~NewArray();

    void setData(int index,int var);
    int getData(int index);
    int length();

    int& operator[](int i);
    NewArray& operator=(NewArray& obj);
    bool operator==(NewArray& obj);
    bool operator!=(NewArray& obj);

private:
    int m_len;
    int *m_buf;
};

#endif // NEWARRAY_H
  • 类的实现文件
#include "newarray.h"

NewArray::NewArray()
{
    m_buf = NULL;
    m_len = -1;
}

NewArray::NewArray(int _len)
{
    if(_len < 0)
        _len = 0;
    m_len = _len;
    m_buf = new int[m_len];

}
NewArray::NewArray(const NewArray & obj)
{
    m_len = obj.m_len;
    m_buf = new int[m_len];
    for(int i = 0;i < m_len;i++)
    {
        m_buf[i] = obj.m_buf[i];
    }
}
NewArray::~NewArray()
{
    if(m_buf != NULL)
    {
        delete []m_buf;
        m_buf = NULL;
        m_len = -1;
    }
}

void NewArray::setData(int index,int var)
{
    m_buf[index] = var;
}
int NewArray::getData(int index)
{
    return  m_buf[index];
}
int NewArray::length()
{
    return m_len;
}

int& NewArray::operator[](int i)
{
    return m_buf[i];
}
NewArray& NewArray::operator=(NewArray& obj)
{
    if(m_buf != NULL)
    {
        delete []m_buf;
        m_len = -1;
        m_buf = NULL;
    }
    m_len = obj.m_len;
    m_buf = new int[m_len];
    for(int i = 0;i < m_len;i++)
    {
        m_buf[i] = obj.m_buf[i];
    }
    return *this;

}
bool NewArray::operator==(NewArray& obj)
{
    if(m_len != obj.m_len)
    {
        return false;
    }
    for(int i = 0;i < m_len;i++)
    {
        if(m_buf[i] != obj.m_buf[i])
        {
            return false;
        }
    }

    return true;
}
bool NewArray::operator!=(NewArray& obj)
{
    return !((*this) == obj);
}
  • 测试文件
#include "newarray.h"
using namespace std;



int main()
{
    NewArray  a1(10);

    for (int i=0; i<a1.length(); i++)
    {
        //成员函数方式赋值
        a1.setData(i, i);
        //下标运算符重载赋值
        a1[i] = i;

        //函数返回值当左值,需要返回一个引用
        //a1.operator [i]
    }

    cout<<"\na1: ";
    for (int i=0; i<a1.length(); i++)
    {
        //cout<<a1.getData(i)<<" ";//成员函数方式获取元素
        //下标运算符方式获取数组元素
        cout<<a1[i]<<"\t";
    }
    cout<<endl;

    //赋值运算符重载
    NewArray a2 = a1;
    cout<<"\na2: ";
    for (int i=0; i<a2.length(); i++)
    {
        cout<<a2.getData(i)<<" ";
    }
    cout<<endl;

    //3
    NewArray a3(5);
    {
        a3 = a1;
        a3 = a2 = a1;

        cout<<"\na3: ";
        for (int i=0; i<a3.length(); i++)
        {
            cout<<a3[i]<<" ";
        }


    }


    //功能4

    if (a3 == a1)
    {
        printf("\nequal\n");
    }
    else
    {
        printf("\nnot equal\n");
    }
    //a3.operator==(a1);
    //bool operator==(Array &a1);


    if (a3 != a1)
    {
        printf("\nnot equal\n");
    }
    else
    {
        printf("\nequal\n");
    }
    //
    //a3.operator!=(a1)
    // bool operator!=(Array &a1);


    cout<<"hello..."<<endl;

    return 1;
}

5.重载函数调用运算符

  • () 运算符用于函数调用
  • 重载格式
类型 类 :: operator() ( 表达式表 ) ;
  • 只能用成员函数重载,不能用友元函数重载

例1
设 x 是类 X 的一个对象,则表达式
x ( arg1, arg2, … )
可被解释为
x . operator () (arg1, arg2, … )
案例:

  • 例2:用重载()运算符实现数学函数的抽象
#include <iostream>
class  F
  { public :  
        double  operator ( )  ( double x ,  double  y ) ;
  } ;
double  F :: operator ( )  ( double  x ,  double  y )
   { return   x * x + y * y ; }
void main ( )           
{ 
F  f  ;
f.getA();
    cout << f ( 5.2 , 2.5 ) << endl ;  // f . operator() (5.2, 2.5)
}
  • 例3 用重载()运算符实现 pk 成员函数
#include <iostream.h>
class  F
  { public :  
        double  memFun ( double x ,  double  y ) ;
  } ;
double  F :: memFun ( double  x ,  double  y )
   { return   x * x + y * y ; }
void main ( )           
{ 
F  f  ;
    cout << f.memFun ( 5.2 , 2.5 ) << endl ;
}

6.不建议重载的运算符

理论知识:
1)&&和||是C++中非常特殊的操作符
2)&&和||内置实现了短路规则
3)操作符重载是靠函数重载来完成的
4)操作数作为函数参数传递
5)C++的函数参数都会被求值,无法实现短路规则

#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
    int i;
public:
    Test(int i)
    {
        this->i = i;
    }

    Test operator+ (const Test& obj)
    {
        Test ret(0);

        cout<<"执行+号重载函数"<<endl;
        ret.i = i + obj.i;
        return ret;
    }

    bool operator&& (const Test& obj)
    {
        cout<<"执行&&重载函数"<<endl;

        return i && obj.i;
    }
};

// && 从左向右
void main()
{
    int a1 = 0;
    int a2 = 1;

    cout<<"注意:&&操作符的结合顺序是从左向右"<<endl;

    if( a1 && (a1 + a2) )
    {
        cout<<"有一个是假,则不在执行下一个表达式的计算"<<endl;
    }

    Test t1 = 0;
    Test t2 = 1;

    //if( t1 && (t1 + t2)  )
    //t1  && t1.operator+(t2)
    // t1.operator&&(  t1.operator+(t2) )   

    //1 && || 重载他们 不会产生短路效果
    if(  (t1 + t2) && t1)
    {
        //t1.operator+(t2) && t1;
        //(t1.operator+(t2)).operator&&(t1);

        cout<<"两个函数都被执行了,而且是先执行了+"<<endl;
    }

    //2 && 运算符的结合性
    // 两个逻辑与运算符  在一块的时候, 采去谈 运算符的结合性
    // 从左到右    (t1 + t2) && t1 ; 运算结果 && t2)
    //if(  (t1 + t2) && t1 && t2)
    {
        //t1.operator+(t2) && t1;
        //(t1.operator+(t2)).operator&&(t1);

        cout<<"两个函数都被执行了,而且是先执行了+"<<endl;
    }

    system("pause");
    return ;
}

5.字符串类的实现

  • 头文件
#ifndef MYSTRING_H
#define MYSTRING_H
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
class MyString
{
public:
    MyString();
    MyString(int _len);
    MyString(const char *_str);
    MyString(const MyString & obj);
    ~MyString();


    MyString& operator =(const MyString & obj);
    MyString& operator =(const char * _str);

    bool operator ==(const MyString & obj);
    bool operator ==(const char * _str);

    bool operator !=(const MyString & obj);
    bool operator !=(const char * _str);

    bool operator >(const MyString & obj);
    bool operator >(const char * _str);

    bool operator <(const MyString & obj);
    bool operator <(const char * _str);

    char& operator [](int index);

    friend ostream& operator<<(ostream & out,MyString & obj);
    friend istream& operator>>(istream & in,MyString & obj);



private:
    int m_len;
    char *m_str;
};

#endif // MYSTRING_H
  • 实现文件
#include "mystring.h"

MyString::MyString()
{
    m_len = 0;
    m_str = NULL;
}
MyString::MyString(int _len)
{
    if(_len < 0)
        _len = 0;
    m_len = _len;
    m_str = new char[m_len+1];
    memset(m_str,0,m_len);
}

MyString::MyString(const char *_str)
{
    if(_str == NULL)
    {
        m_len = 0;
        m_str = new char[m_len+1];
        strcpy(m_str,"");
    }else
    {
        m_len = strlen(_str);
        m_str = new char[m_len+1];
        strcpy(m_str,_str);
    }

}
MyString::MyString(const MyString & obj)
{
    m_len = obj.m_len;
    m_str = new char[m_len+1];
    strcpy(m_str,obj.m_str);
}
MyString::~MyString()
{
    if(m_str != NULL)
    {
        delete []m_str;
        m_str = NULL;
        m_len = 0;
    }
}

MyString& MyString::operator =(const MyString & obj)
{
    if(m_str != NULL)
    {
        delete []m_str;
        m_str = NULL;
        m_len = 0;
    }
    m_len = obj.m_len;
    m_str = new char[m_len+1];
    strcpy(m_str,obj.m_str);
    return *this;
}

MyString& MyString::operator =(const char * _str)
{
    if(m_str != NULL)
    {
        delete []m_str;
        m_str = NULL;
        m_len = 0;
    }

    if(_str == NULL)
    {
        m_len = 0;
        m_str = new char[m_len+1];
        strcpy(m_str,"");
    }else
    {
        m_len = strlen(_str);
        m_str = new char[m_len+1];
        strcpy(m_str,_str);
    }

    return *this;
}

bool MyString::operator ==(const MyString & obj)
{
    if(m_len != obj.m_len)
    {
        return false;
    }
    return !strcmp(m_str,obj.m_str);

}

bool MyString::operator ==(const char * _str)
{
    if(_str == NULL)
    {
        if(m_len == 0)
        {
            return true;
        }else{

            return false;
        }
    }else{
        if(m_len == strlen(_str)){
            return !strcmp(m_str,_str);
        }else{
            return false;
        }
    }


}

bool MyString::operator !=(const MyString & obj)
{
    return !((*this) == obj);
}

bool MyString::operator !=(const char * _str)
{
    return !((*this) == _str);
}

bool MyString::operator >(const MyString & obj)
{
    if(strcmp(m_str,obj.m_str) > 0)
    {
        return true;
    }else{
        return false;
    }
}

bool MyString::operator >(const char * _str)
{
    if(strcmp(m_str,_str) > 0)
    {
        return true;
    }else{
        return false;
    }
}

bool MyString::operator <(const MyString & obj)
{
    if(strcmp(m_str,obj.m_str) < 0)
    {
        return true;
    }else{
        return false;
    }
}

bool MyString::operator <(const char * _str)
{
    if(strcmp(m_str,_str) < 0)
    {
        return true;
    }else{
        return false;
    }
}

char& MyString::operator [](int index)
{
    return m_str[index];
}

ostream& operator<<(ostream & out,MyString & obj)
{
    out<<obj.m_str;
    return out;
}

istream& operator>>(istream & in,MyString & obj)
{
    in>>obj.m_str;
    return in;
}
  • 测试文件
#define _CRT_SECURE_NO_WARNINGS

#include "mystring.h"



void main01()
{
    MyString s1;
    MyString s2("s2");
    MyString s2_2 = NULL;
    MyString s3 = s2;
    MyString s4 = "s4444444444";

    //测试运算符重载 和 重载[]
    //=

    s4 = s2;
    s4 = "s2222";
    s4[1] = '4';
    printf("%c", s4[1]);

    cout<<s4 <<endl;
    //ostream& operator<<(ostream &out, MyString &s)

    //char& operator[] (int index)
    //MyString& operator=(const char *p);
    //MyString& operator=(const MyString &s);

    cout<<"hello..."<<endl;
    system("pause");
    return ;
}

void main02()
{
    MyString s1;
    MyString s2("s2");

    MyString s3 = s2;

    if (s2 == "aa")
    {
        printf("相等");
    }
    else
    {
        printf("不相等");
    }

    if (s3 == s2)
    {
        printf("相等");
    }
    else
    {
        printf("不相等");
    }

}
void main03()
{
    MyString s1;
    MyString s2("s2");

    MyString s3 = s2;
    s3 = "aaa";

    if (s3 < "bbbb" )
    {
        printf("s3 小于 bbbb");
    }
    else
    {
        printf("s3 大于 bbbb");
    }

    MyString s4 = "aaaaffff";
    //strcpy(s4.c_str(), "aa111"); //MFC
    cout<<s4<<endl;
}

void main011()
{
    MyString s1(128);
    cout<<"\n请输入字符串(回车结束)";
    cin>>s1;

    cout<<s1;
    system("pause");

}

int main()
{
    MyString s1(128);
    cout<<"\n请输入字符串(回车结束)";
    cin>>s1;

    cout<<s1<<endl;

    system("pause");

    return 0;

}

总结

  • 操作符重载是C++的强大特性之一
  • 操作符重载的本质是通过函数扩展操作符的语义
  • operator关键字是操作符重载的关键
  • friend关键字可以对函数或类开发访问权限
  • 操作符重载遵循函数重载的规则
  • 操作符重载可以直接使用类的成员函数实现
  • =, [], ()和->操作符只能通过成员函数进行重载
  • ++操作符通过一个int参数进行前置与后置的重载
  • C++中不要重载&&和||操作符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值