第四周学习

4.1运算符重载

  • 对已有的运算符赋予多重的含义
  • 使同一运算符作用于不同类型的数据时能够有不同的功能
  • 扩展c++中运算符的功能
    5+4=9
    5+6i+7+3i=12+9i
  • 运算符重载的实质是函数的重载
    返回值类型 operator 运算符(形参表){…}
class complex{
public:
    complex(int a,int b){real=a;imag=b;}
    int real,imag;
    complex operator+(const complex& a){
    return complex(real+a.real,imag+a.imag)
}//重载为成员函数的时候只需要一个参量。
};
    complex::complex operator+(const complex &a,const complex &b){
    return complex(a.real+b.real,a.imag+b.imag)
}//重载为普通函数的时候为两个参量,为运算符目数。两者是等价的

4.2赋值运算符 = 的重载

  • 可以将赋值运算符重载为想要的功能,比如把int赋值给complex等。
  • 赋值运算符 = 只能重载为成员函数

e.g 自己的string类

#include <iostream>
using namespace std;

class String{
private:
    char *str;
public:
    String():str(NULL){}
    const char *c_str(){return str;}
    char *operator =(const char *s);
    ~String();
    String(const char *s1){
        str=new char[strlen(s1)+1];
        strcpy(str,s1);//用*char可以完成,strcpy做的是拷贝的工作,将后者拷贝给前者
    }
};

char *String::operator=(const char *s){
    if(str) delete[] str;
    if(s){
        str=new char[strlen(s)+1];
        strcpy(str,s);
    }else{
        str=NULL;
    }
    return str;
}

String::~String(){
    if(str) delete[] str;
}

int main(){
    String s;
    s="good sdf";//为了满足这个等号,需要对赋值运算符进行重载
    String s2="hello lsidfh";
    cout<<s.c_str()<<endl;//s.c_str()目的是返回一个*char
    cout<<s2.c_str()<<endl;
    return 0;
}

深拷贝和浅拷贝

  • 当自己不定义复制构造函数的时候,系统会自动生成一个复制构造函数,将原有的内容一字节一字节的拷贝给新的对象。
  • 但有时候,我们并不希望如此,当对象的成员变量有指针的时候,会出现以下情况:a对象和b对象的指针内容在相同的内存空间中,则可以通过b对象的成员指针改变a对象的内容,这不是我们想要的
  • 于是有了深拷贝,需要对新对象的指针对象开辟新的空间,并复制原来对象的内容进去,这样,虽然先后两个对象的指针变量指的内容是一致的,但在内存空间中是不同的位置,不会相互影响

4.3运算符重载为友元函数

  • 成员函数不能满足使用需求,而普通函数不能访问类私有成员
    例如,现有一个类名叫complex,要实现complex+5,可以通过成员函数的重载实现,这句话等于complex.+(5),但若想要实现5+complex,需要对整体的 + 进行重载,就不能是成员函数,而是要普通函数,而普通函数不能访问类的私有成员,所以只能是友元函数才可以。
class complex{
private:
    double real,imag;
public:
    complex(double r, double i):real(r),imag(i){};
    complex operator+ (double r){
        return complex(real+r,imag);
    }//对于后置的加号,只要通过成员函数即可实现
};
int main(){
    complex a(2,3),b(1,1);
    b=a+5;//完成后置加号的重载
    return 0;
}

对于前置加号,只能通过重载为友元实现

class complex{
private:
    double real,imag;
public:
    complex(double r, double i):real(r),imag(i){};
    complex operator+ (double r){
        return complex(real+r,imag);
    }
friend complex operator+ (double r,const complex& c);//申明友元函数
};
complex operator+ (double r,const complex& c){
    return complex(c.real+r,c.imag);
}//定义普通函数operator+
int main(){
    complex a(2,3),b(1,1);
    b=a+5;
    b=5+a;
    return 0;
}

4.4 e.g.可变长整形数组

  • 需求,编写一个程序,完成动态可变数组,需要多大的数组,就可以扩大成为那么大的。
    需要实现的c++主程序:
int main(){
    CArray a;//创建一个可变数组对象
    for(int i=0;i<5;++i){
        a.push_back(i);//支持push_back函数加入新的元素
    }
    CArray a2,a3;
    a2=a;//可以通过等号进行深拷贝
    for(int i=0;i<a.length();++i){
        cout<<a2[i]<<" ";//支持流输出运算符
    }
    a2=a3;
    for(int i=0;i<a2.length();++i){
        cout<<a2[i]<<" ";
    }
    cout<<endl;
    a[3]=100;//支持直接调用
    CArray a4(a);//支持这样构造
    for(int i=0;i<a4.length();++i){
        cout<<a4[i]<<" ";
    }
    return 0;
}

实现:

#include <iostream>
using namespace std;
class CArray{
public:
    int *a1;
    int size;
    void push_back(const int &a){//将新的地址加上新的元素赋值给旧的
        int *p2;
        int *p1;
        int *a3;
        a3=a1;
        p1=new int[size+1];
        p2=p1;
        for(int i=0;i<size;++i){
            *p2=*a3;
            ++p2;
            ++a3;
        }
        *p2=a;
        ++size;
        a1=p1;
        delete p1;
    }
    CArray (CArray &a){//深拷贝
        size=a.size;
        int *p1;
        int *p2;
        p1=new int[size];
        p2=p1;
        for(int i=0;i<size;++i){
            *p2=*(a.a1+i);
            ++p2;
        }
        a1=p1;
        delete [] p1;
    }
    CArray(){size=0;}
    int length(){return size;}
    int & operator[](int i){//实现[]调用
        return a1[i];
    }
    ~CArray(){//检查是否还有未删除的指针
    if(a1){delete [] a1;}
    }
};

int main(){
    CArray a;
    for(int i=0;i<5;++i){
        a.push_back(i);
    }
    CArray a2,a3;
    a2=a;

    for(int i=0;i<a.length();++i){
        cout<<a2[i]<<" ";
    }
    a2=a3;
    for(int i=0;i<a2.length();++i){
        cout<<a2[i]<<" ";
    }
    cout<<endl;
    a[3]=100;
    CArray a4(a);
    for(int i=0;i<a4.length();++i){
        cout<<a4[i]<<" ";
    }
    return 0;
}

4.5流插入运算符和流提取运算符的重载

  • 若想输出或者输入某个类,就要对其进行重载,重载为ostream/istream的引用
    e.g.
    假设c是complex复数类的对象,现在希望写 “cout<
#include <iostream>
using namespace std;

class Complex{
private:
    double real,imag;
public:
Complex(int a=0,int b=0):real(a),imag(b){}
friend ostream &operator<<(ostream & o,const Complex &s);
friend istream &operator>>(istream & o,Complex &s);//申明友元的重载
};

ostream &operator<<(ostream & o,const Complex &s){
    o<<s.real<<"+"<<s.imag<<"i";
    return o;
}
istream &operator>>(istream & o,Complex &c){
    string s;
    o>>s;
    int pos=s.find("+",0);
    string stmp=s.substr(0,pos);
    c.real=atof(stmp.c_str());
    stmp=s.substr(pos+1,s.length()-pos-2);
    c.imag=atof(stmp.c_str());
    return o;
}
int main(){
    Complex c;
    int n;
    cin>>c>>n;
    cout<<c<<","<<n;
    return 0;
}

4.6自加/自减运算符的重载

  • 自加自减运算符分前置后置分别进行重载
  • 前置运算符作为一元运算符重载
  • 重载为成员函数时,变量减一

    • T operator++();
    • T operator–();
  • 重载为全局函数,变量为一

    • T operator++(T);
    • T operator–(T);
  • 后置运算符作为二元运算符重载

  • 重载为成员函数时候,变量减一,多写一个参数,具体无意义
    • T operator++(int)
    • T operator–(int)
  • 重载为全局函数的时候,有两个变量
    • T operator++(T, int)
    • T operator–(T, int)
#include <iostream>
using namespace std;
class cdemo{
private:
    int a;
public:
    friend ostream &operator<<(ostream &o,cdemo &s);
    cdemo(int i):a(i){}
    cdemo &operator ++(){//前置,不需要加变量
        a++;
        return *this;
    }
    cdemo &operator ++(int){//后置,需要加个变量
        cdemo tmp(*this);
        a++;
        return tmp;
    }
};
ostream &operator<<(ostream &o,cdemo &s){//流输出重载
    o<<s.a;
    return o;
}
int main(){
    cdemo d(5);
    cout<<(d++)<<",";
    cout<<d<<",",
    cout<<(++d)<<",";
    cout<<d<<endl;
    cout<<(d--)<<","
    cout<<d<<",";
    cout<<(--d)<<","
    cout<<d<<",";
    cout<<d<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值