C++之运算符重载

一、类中的六个默认的成员函数

假如我们现在定义一个类

class Test

{

public:
    int GetData()const
    {
        return m_data;
    }
private:
    int m_data;

};

  • 1.构造函数

1、名字和类名相同

2.无返回值。

3.对象实例化时编译器自动调用对应的构造函数

4.构造函数可以重载

Test (int data=0)

{
        cout << "Create Test Obj : " << this << endl;
        m_data = data;
}

  • 2.拷贝构造函数

1.拷贝构造函数是构造函数的一共重载形式

2.拷贝函数的参数只有一个且必须使用引用传参,传值方式会引发无穷递归调用

3.若未显示定义,系统生成默认的拷贝构造函数。默认的拷贝构造函数对象按成员拷贝

          (后面的当类成员值为指针的话就不行 )

Test(const Test &t)

{

cout<<"copy success!"<<endl;

   m_data=t.m_data;

}

3.赋值运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类 型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

3、操作符有一个默认的形参this,限定为第一个形参 .* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

Test& operator&=(const &Test t)

{

cout << "Assign :" << this << " = " << &t << endl;

  if(this! = &t)                 //判断是否是给自己赋值

   {

      m_data=t.m_data;

   }

return *this;

}

注意:

1、这里的参数使用引用传递是为了提高效率,加上const是为了不改变原来参数的值

2、有返回值是为了能够实现连等的实现

         如       Test  t1=t2=t3=t4;

  • 4.析构函数

~Test()
    {
        cout << "Free Test Obj : " << this << endl;
    }

二、各函数在调用中的体现

例子:

Test fun(Test& x)
{
	int value = x.GetData();
	Test tmp(value);
	return tmp;

}
void main()
{
	Test t(1);
	Test t1;
	t1 = fun(t);
}

 可以看到,fun()函数刚一结束,tmp就被析构了,是靠的无名临时变量把值传递给了t1;

2.不能引用返回局部变量

 引用返回确实效率高,但在面对局部变量的话,就不适用了

局部变量在一跳出函数的时候就会被析构,

如果引用返回的话,那么就不会创建临时的无名变量,那么就接收不到值了

3.最优化的代码

 编译器是很聪明的,在这里他直接把无名临时对象当成t1了(这样效率高的很)

.既然不定义也默认生成成员函数,为什么还要自己去定义呢?

请看下列代码:

 当类成员包含指针的时候,我们可以看到明显的报错,这种情况(系统默认的函数已经不起作用了)我们就必须自己去定义函数了。

1.构造函数

所以这时候的构造函数就要change一下了

 2.析构函数

假如不自己去定义析构函数的话,就会导致内存泄漏

因为m_data的空间被申请出来了,但是却一直没有被释放,所以就内存泄漏了(只申请,没释放)

(使用vld能够查看到内存泄漏的情况)

3、深拷贝构造函数

我们先来看一个现象:

当我们不自己定义拷贝构造函数的时候:

我们运行到即将退出程序的倒数第二步的时候都是正常的

 但最后一步一执行,就立马出现了错误

这是为什么呢?

原因:      

在退出主函数的时候,会调用析构函数,但我们的拷贝构造函数在执行的时候进行的是浅拷贝(成员拷贝)

 那么析构的时候,S1和S2都析构了一次,这就意味着这给空间被释放了两次,

这就导致了典型的错误:  double  free

 所以我们就要自己定义拷贝构造函数去进行深拷贝

4、深赋值

四、运算符重载的实现

                                首先要理解:运算符重载的本质就是函数调用

1、重载之加减乘除

 

 提高了程序的可读性,

这些个函数都是成员函数,有this指针的存在,所以写的时候会看起来少一个参数。

2、重载之前加加与后加加

前加加

 后加加

 这里就能从本质上看出来前加加的效率会更高

3、重载之友元函数

我们先来看一段代码: 

明明只是交换一下顺序,a+10可以,10+a就不行了,为什么呢?

这是因为,对象在前面时,可以驱动这个函数(成员函数),但对象在后面的话,就不能够起到驱动的功能

要想实现10+a的话,就必须定义友元函数:

 定义友元函数的时候,需要在前面加上一共friend关键字

具体写函数的时候,需要在类的外面去写函数的具体实现。

且友元函数,能访问类的私有(相当于成了这个类的朋友),打破了安全性和封装性

友元不是成员,那么就肯定没有this指针,所以写的时候就比成员函数多了一个参数

4、输入输出流重载 

如果直接输出的话,是实现不了的,这时候就要定义输出流的重载

更加了解输出流重载:

当没有返回值的时候

 这时候也是可以直接单独输出t的

但是一旦加上了换行,就会发生明显的报错,这是因为什么呢?

当没有返回值的时候,

 

 因为没有返回值,在第一次有"<<"符号的时候,就会去调用一下运算符的重载,

第二次的时候就变成了”“<<endl,这时候就没有cout在去传参

 当返回值为ostream&的时候,对于cout<<t<<endl一句话,

本质上就是调用了两次输出流重载函数,第一次调用后变为了cout<<endl,会进行第二次调用

5、字符串的运算符重载

      1、+=

 

 2、+

其实运算符的重载主要就是为了提高代码的可读性,

重载就是通过operator告诉编译器我们重载的方法的


总结

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值