c++运算符重载与拷贝问题

运算符重载

加法运算符重载

在这里插入图片描述
调用本质和方法都在上面。

左移运算符重载

在这里插入图片描述
注意到输入流和输出流也可以看成一个类,和int其实没有什么差别,至于&,返回一个输出流的引用是因为该类只有一个,不能拷贝(我的理解目前是这样,估摸着不怎么精准,大家将就看哈)

递增运算符重载

在这里插入图片描述
这里注意后置++是一个死写法,记住就好了,int 只是一个占位符,为了通过参数的不同达到重载函数的目的

赋值运算符重载

这个通常会和地址挂钩,故而涉及到浅拷贝和深拷贝的问题,将与拷贝问题一起展示

可重载的运算符

在这里插入图片描述

不可重载的运算符

在这里插入图片描述

练习一下运算符重载吧~

题目如下:

有位同学不小心把写了一半的代码弄乱了,不仅丢失了一些代码,里面还被小精灵混入了大量不可见的魔国符号,请你帮他把代码梳理清楚,并将他的错误更正。

using namespace std; class Counter{ public:  Counter(){value=0;}

Counter(int i){value=i;}   friend Counter operator ++(Counter &);   friend Counter operator (Counter c1,Counter c2);   void display(){cout<<value<<endl;}  private:  unsigned value;  };  Counter operator ++(Counter &p) {  p.value++;  return p; }  Counter operator (Counter c1,Counter c2) {  Counter temp;   temp.value=c1.valuec2.value;  return temp; } int main() {  Counter ctr,ctr1; cin>>ctr;cin>>ctr1;ctr++; ctr2=ctrctr1; //ctr3.display();  return 0;}

【输入形式】

两个整数
【输出形式】

一个整数
【样例输入】

5 6
【样例输出】

36

解决代码示例
#include "iostream"
using namespace std;
class Counter
{
    friend Counter operator++(Counter &p);//运用友元的知识
    friend Counter operator *(Counter c1,Counter c2);
    friend istream &operator>>(istream &cin,Counter &p);
public:
      Counter()//构造函数
      {
          value=0;
      }
    
    void display(){cout<<value<<endl;}

private:
    unsigned  int value;
};

Counter operator++(Counter &p)
{
    p.value++;
    return p;
}
Counter operator *(Counter c1,Counter c2)
{
    Counter temp;
    temp.value=c1.value*c2.value;
    return temp;
}
istream &operator>>(istream &cin,Counter &p)
{
    cin>>p.value;
}
int main()
{
    Counter ctr,ctr1,ctr2;
    cin>>ctr;
    cin>>ctr1;
    ++ctr;
    ctr2=ctr*ctr1;
    ctr2.display();
    return 0;
}

怎么样,是不是掌握了呢~

拷贝问题

为什么会有拷贝问题

浅拷贝:
    简单的赋值拷贝操作,地址也是一样的
深拷贝:
   在堆区中重新申请空间,进行拷贝操作
浅拷贝带来的问题就是堆区的重复释放,解决方案便是自己实现拷贝构造函数
                   栈区的规则是先进后出
               自动释放的内存是栈区的变量而不是堆区的

代码示例

#include <iostream>
#include <cstring>
using namespace std;

class Person
{
public :
    string name;
    int *p;
    Person(){}           //默认构造函数
    Person(const Person &b)  //深拷贝构造函数
    {
        name=b.name;
        p=b.p;
        p=new int [10];//给该对象也开辟一个内存
        for(int i=0;i<10;i++)
        {
            p[i]=b.p[i];
        }
    }
    Person & operator=(const Person &b)   //重载赋值运算符
    {
        name=b.name;
        p=b.p;
        return *this;
    }
};

int main()
{
    Person j;
    j.name="jz";
    j.p=new int[10];//给j对象在堆区开辟了一块内存
    for(int i=0;i<10;i++)
        j.p[i]=i;
        //Person y=j;
    Person y;
    y=j;
    y.p[0]=200;
    cout << j.p[0] << endl;
    return 0;
 }

示例2

class Person
{
public:
    Person(int age)
    {
        m_Age=new int (age);
    }
    ~Person()
    {
        if(m_Age!=NULL)
        {
            delete m_Age;
            m_Age=NULL;
        }
    }
    //重载 赋值运算符
    Person& operator=(Person &p)
    {
        //编译器提供的是浅拷贝
       // m_Age=p.m_Age;
        //应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
            if(m_Age!=NULL)//this->m_Age!=NULL
            {
                delete m_Age;
                m_Age=NULL;
            }
               m_Age= new int (*p.m_Age)//深拷贝
               return *this;//返回对象本身
    }
    int *m_Age;
};

void test01()
{
    Person p1(18);
    cout<<"p1的年龄为: "<<p1.m_Age<<endl;
    cout<<"p1的年龄为: "<<*p1.m_Age<<endl;
    Person p2(20);
    p2=p1;//赋值操作
    cout<<"p2的年龄为: "<<p2.m_Age<<endl;
    cout<<"p2的年龄为: "<<*p2.m_Age<<endl;
}

int main()
{
    int a=10;
    int b=20;
    int c=30;
    c=b=a;//输出全都是10;

}

默认构造函数小记

//注意: &读作at,在函数申明的时候是引用的意思,其他的时候才是取地址

class w
{
public:
    int a,b;
    w(){}//
    w(int i_a,int i_b):a(i_a),b(i_b){}
    w(int i_a,int i_b)
    {
        a=i_a;
        b=i_b;
    }
    w(const w&w1)//有参普通构造
    {
        this->a=w1.a;
        this->b=w1.b;
        cout<<"构造"<<endl;
    }

    w&operator=( const w &w1)//重载赋值运算符
    {
        cout<<"赋值"<<endl;
        this->a=w1.a;
        this->b=w1.b;
        return *this;    //返回该类的值,例如 a=b,写在类A里面,this表示是类A的指针,指向该类本身的某一个实例化对象,*this表示a
        //  this表示运算符前面的那个操作数
    }

};


int main()
{
    w w1;
    w1.a=100;
    w1.b=100;

    w w2;//调用第1个
    w2=w1;//调用第3个
    //w w3(w1);  初始化
    w w3=w1;//调用第2个,与上面一个等价.
    cout<<w2.a<<" "<<w2.b<<endl;
    return 0;
}

作者小记

这是临近期末的学习笔记,今天耗时9小时才从0学会了这么一点点。可能有些零碎,大家也请多多包含。有什么不对或者更好的见解也欢迎留言呀。喜欢也可以关注我哦~学习路上会努力!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值