C++学习笔记13——模板篇

别说谁变了你拦得住时间么 提交于 2020-02-22 23:38:56

教程:https://www.imooc.com/learn/477

运算符重载:给原有运算符赋予新功能

在这里插入图片描述
上图,用+连接多个字符串使其拼接成一个字符串str3,打印的时候可以直接把这个字符串打印出来,则这个字符串进行了多个运算符的重载,+也进行了重载,cout也进行了重载,=也进行了重载

在这里插入图片描述
上图,原来+并不具备这样子把两个坐标相加的功能,需要对其进行重载,要这样子把坐标输出,也要对输出运算符进行重载

运算符重载的本质:函数重载
关键字:operator

一元运算符重载(这里以-、++举例)
一元运算符:这个符号只与一个操作数进行运算
如:+(加法)是二元运算符,因为需要两个操作数,但把+放在一个操作数前面,就是一元运算符,就像-放在一个操作数前面,也是一元运算符,对操作数取反
在这里插入图片描述
友元函数重载:在类中定义一个友元函数,这个友元函数是一个全局函数,用这个友元函数进行运算符重载,从而实现一个符号的理想功能
成员函数重载:实际上就是定义一个成员函数

在这里插入图片描述
上图标红句子是对-进行运算符重载,()里没有参数是因为是一元运算符,而且是作为类的成员函数存在的,所以不需要传任何参数,但里面是有一个隐性的this指针的,而这个隐性的this指针就是其操作数,如下图,将每个数据成员取反,再重新赋值给他本身:
在这里插入图片描述
使用:
在这里插入图片描述
看到-coor1; 计算机会自动解释为注释,相当于一个函数的调用

友元函数的重载

在这里插入图片描述
用friend全局声明一个函数“operator-”
传入的参数是Coordinate的引用,返回值也是Coordinate的引用
在这里插入图片描述
实现的时候,通过这个引用变量,分别对每一个数据成员取反,并赋值给本身,用this返回

实现:
在这里插入图片描述
对比:成员函数重载,是coor1.operator-();
友元函数重载,是operator-(coor1);

++符号的重载

在这里插入图片描述
前置++符号重载:将++写在操作数前面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
后置++符号重载:
在这里插入图片描述
注意:1、返回值不是引用,而是Coordinate的一个对象(前置的是引用)2、operator++后一定要传入一个int,作为一个标识,表示当前operator++做的是后置重载。在使用时,这个int不用传入任何值,传了也没意义,因为不会使用到
在这里插入图片描述

Coordinate old(*this);为保证有一个旧的值,先定义一个临时对象old,将当前的值保存到临时兑现old中。最后通过return old;返回
所以如果接收到后置++的值,那也是++前的值,下行代码再去使用这个值的时候,这个值才会发生变化
使用:
在这里插入图片描述
传入的0是个标识

编码示例:

负号成员函数的重载:
当前采用的是引用的方式:
Coordinate.h

#ifndef  COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
public:
	Coordinate(int x, int y);
	Coordinate &operator-();
	int getX();
	int getY();
private:
	int m_iX;
	int m_iY;
};

#endif // ! COORDINATE_H

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

Coordinate &Coordinate::operator-()
{
	this->m_iX = -(this->m_iX);  //括号可加可不加
	m_iY = -m_iY; //两种写法都可以
	return *this;
}

demo.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	-coor1; //相当于 coor1.operator-();
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	return 0;
}

在这里插入图片描述
友元函数的负号重载:
Coordinate.h

#ifndef  COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
	friend Coordinate &operator-(Coordinate &c); //括号内的参数就是成员函数运算符重载括号中的this,在这里体现为Coordinate的一个对象。可以写Coordinate c  为了传递效率,也可以再加个&
public:
	Coordinate(int x, int y);
	//Coordinate &operator-();  //成员函数运算符重载
	int getX();
	int getY();
private:
	int m_iX;
	int m_iY;
};

#endif // ! COORDINATE_H

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

/* Coordinate &Coordinate::operator-()  //成员函数运算符重载
{
	this->m_iX = -(this->m_iX);  //括号可加可不加
	m_iY = -m_iY; //两种写法都可以
	return *this; */

Coordinate &operator-(Coordinate &c)  //友元函数运算符重载 ,是全局的,不属于任何一个类
{
	c.m_iX = -c.m_iX;  
	c.m_iY = -c.m_iY; 
	return c;
}

demo.cpp (使用没有变,只是改了一下注释)

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	-coor1; //相当于 operator-(coor1);
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	return 0;
}

前置++成员函数的重载:
Coordinate.h

#ifndef  COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
	friend Coordinate &operator-(Coordinate &c); //括号内的参数就是成员函数运算符重载括号中的this,在这里体现为Coordinate的一个对象。可以写Coordinate c  为了传递效率,也可以再加个&
public:
	Coordinate(int x, int y);
	Coordinate &operator++();  //前置++成员函数的重载
	//Coordinate &operator-();  //成员函数运算符重载
	int getX();
	int getY();
private:
	int m_iX;
	int m_iY;
};

#endif // ! COORDINATE_H

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

/* Coordinate &Coordinate::operator-()  //成员函数运算符重载
{
	this->m_iX = -(this->m_iX);  //括号可加可不加
	m_iY = -m_iY; //两种写法都可以
	return *this; */

Coordinate &Coordinate::operator++()  //前置++,返回的值是++之后的值
{
	m_iX++;  //++m_iX;
	m_iY++;  //++m_iY;  两种写法都可以
	return *this;
}

Coordinate &operator-(Coordinate &c)  //友元函数运算符重载 ,是全局的,不属于任何一个类
{
	c.m_iX = -c.m_iX;  
	c.m_iY = -c.m_iY; 
	return c;

demo.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	++ coor1;
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	//-coor1; //相当于 operator-(coor1);
	//cout << coor1.getX() << " , " << coor1.getY() << endl;
	return 0;
}

在这里插入图片描述
后置++成员函数的重载:
Coordinate.h

#ifndef  COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
	friend Coordinate &operator-(Coordinate &c); //括号内的参数就是成员函数运算符重载括号中的this,在这里体现为Coordinate的一个对象。可以写Coordinate c  为了传递效率,也可以再加个&
public:
	Coordinate(int x, int y);
	Coordinate &operator++();  //前置++成员函数的重载
	Coordinate operator++(int); //后置++成员函数的重载   返回的是Coordinate的对象而不是引用,因为后置++,返回的是++之前的值,下一句再使用的时候才是++后的
	//Coordinate &operator-();  //成员函数运算符重载
	int getX();
	int getY();
private:
	int m_iX;
	int m_iY;
};

#endif // ! COORDINATE_H

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

/* Coordinate &Coordinate::operator-()  //成员函数运算符重载
{
	this->m_iX = -(this->m_iX);  //括号可加可不加
	m_iY = -m_iY; //两种写法都可以
	return *this; */

Coordinate &Coordinate::operator++()  //前置++,返回的值是++之后的值
{
	m_iX++;  //++m_iX;
	m_iY++;  //++m_iY;  两种写法都可以
	return *this;
}

Coordinate Coordinate::operator++(int)
{
	Coordinate old(*this);  //临时对象,直接赋值:把this放进去,此时用到拷贝构造函数,因为没有在用到类型为指针的数据成员,也没有再类中实例化对象,所以用默认拷贝构造函数,如果做了特殊处理,可能要重载拷贝构造函数
	this->m_iX++;
	this->m_iY++;
	return old;  //注意是old不是this,以实现在当前表达式得到的是++前的值,在表达式之后运行的对象是++后的值
}

Coordinate &operator-(Coordinate &c)  //友元函数运算符重载 ,是全局的,不属于任何一个类
{
	c.m_iX = -c.m_iX;  
	c.m_iY = -c.m_iY; 
	return c;
}

demo.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	cout << coor1.getX() << " , " << coor1.getY() << endl;
	cout << (coor1++).getX() << " , "; //coor1++前的值,此时拿到的是1
	cout << (coor1++).getY() << endl;  //coor1在上行以++过一次,此时拿到的是上行++过的,即4
	cout << coor1.getX() << " , " << coor1.getY() << endl;  //本行得到的是经过上两行++后的
	return 0;
}

在这里插入图片描述

二元运算符重载

+号成员函数重载:
在这里插入图片描述
参数是第二个加数,第一个加数默认是当前对象
在这里插入图片描述
定义一个Coordinate类型的临时对象,coor的和当前的(this)相加赋给temp
在这里插入图片描述
标红句的+已经重载
+号友元函数重载:
定义:
在这里插入图片描述
写了const就不能改c1、c2的值
实现:
在这里插入图片描述
使用:
在这里插入图片描述
<<号运算符:
定义:
在这里插入图片描述
声明为友元函数,返回值必须是ostream&,传入的第一个参数也必须是ostream &out(out可改),第二个参数是输出的对象
实现:
在这里插入图片描述
用ostream &out这个对象替代输出语句的cout,其他的写法不变,return out(out可变)也是必须的
使用:
在这里插入图片描述
从以上可理解,cout是ostream的一个对象

**输出运算符不可以采用成员函数重载,只能用友元函数。**原因:由+成员函数重载知,第一个参数是当前对象。对于输出运算符来说,第一个对象必须是ostream,这就意味着第一个参数不能是this指针,即不能是当前对象。

[]索引运算符:
声明:
在这里插入图片描述
实现:
在这里插入图片描述
如果两个都不是,应该抛出异常(上图没有处理)
使用:
在这里插入图片描述
传入0打印X,传入1打印Y

索引运算符不可以采用友元函数重载,必须用成员函数重载,友元函数重载第一个参数可以是成员函数重载中的this指针,也可以是其他的值,但作为索引运算符,第一个参数必须是this指针,因为只有第一个参数是this指针,才可以传入索引,才能使这个索引表达的是当前的对象中的成员

二次运算符重载编码示例:

+号运算符成员函数重载:
Coordinate.h

#ifndef  COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
public:
	Coordinate(int x, int y);
	Coordinate operator+(Coordinate &c);  //+号运算符成员函数重载,第一个参数是this指针,第二个参数是()内容
	int getX();
	int getY();
private:
	int m_iX;
	int m_iY;
};

#endif // ! COORDINATE_H

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

Coordinate Coordinate::operator+(Coordinate &c)
{
	Coordinate temp(0, 0);
	temp.m_iX = this->m_iX + c.m_iX; //当前对象的+参数传入的 结果赋给临时的
	temp.m_iY = this->m_iY + c.m_iY;
	return temp;
}

demo.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	Coordinate coor2(2, 4);
	Coordinate coor3(0, 0);

	coor3 = coor1 + coor2;
	cout << coor3.getX() << " , " << coor3.getY() << endl;
	return 0;
}

+号运算符友元函数重载:
修改:
Coordinate.h

#ifndef  COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
	friend Coordinate operator+(Coordinate c1, Coordinate c2);  //+号运算符友元函数重载
public:
	Coordinate(int x, int y);
	int getX();
	int getY();
private:
	int m_iX;
	int m_iY;
};

#endif // ! COORDINATE_H

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

Coordinate operator+(Coordinate c1, Coordinate c2)
{
	Coordinate temp(0, 0);
	temp.m_iX = c1.m_iX + c2.m_iX;
	temp.m_iY = c1.m_iY + c2.m_iY;
	return temp;
}

在这里插入图片描述
输出运算符的重载:
Coordinate.h增加:

friend ostream &operator<<(ostream &output, Coordinate &coor);

Coordinate.cpp增加:

ostream &operator<<(ostream &output, Coordinate &coor)
{
	output << coor.m_iX << "," << coor.m_iY;
	return output;
}

demo.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	Coordinate coor2(2, 4);
	Coordinate coor3(0, 0);
	coor3 = coor1 + coor2;

	cout << coor3 << endl;
	return 0;
}

在这里插入图片描述
[]索引运算符的重载:
Coordinate.h在public下增加:

int operator [](int index);

Coordinate.cpp增加:

int Coordinate::operator [](int index)
{
	if (index == 0)
	{
		return m_iX;
	}
	if (index == 1)
	{
		return m_iY;
	}
}

demo.cpp

#include "Coordinate.h"
#include <iostream>
using namespace std;

int main()
{
	Coordinate coor1(1, 3);
	Coordinate coor2(2, 4);
	Coordinate coor3(0, 0);
	coor3 = coor1 + coor2;

	cout << coor3 [0]<< endl;  //输出m_iX
	cout << coor3[1] << endl;  //输出m_iY
	return 0;
}

在这里插入图片描述
综合:

#include <iostream>
using namespace std;

/**
 * 定义Coordinate类
 * 数据成员:m_iX,m_iY
 * 成员函数:构造函数
 * 重载--运算符,重载+运算符
 */
class Coordinate
{
public:
    Coordinate(int x, int y)
	{
		m_iX = x;
		m_iY = y;
	}
    // 前置--运算符重载
	Coordinate &operator--()
	{
	    m_iX--;
	    m_iY--;
	    return *this;
	}
	
    // 后置--运算符重载
    Coordinate &operator--(int)
    {
        Coordinate old(*this);
        this->m_iX--;
        this->m_iY--;
        return old;
    }
    
    // +号运算符重载
	Coordinate operator+(Coordinate &c)
	{
	    Coordinate temp(0,0);
	    temp.m_iX = this->m_iX + c.m_iX;
	    temp.m_iY = this->m_iY + c.m_iY;
	    return temp;
	}
    
    

public:
	int m_iX;
	int m_iY;
};

int main(void)
{
	Coordinate coor1(1, 3);
	Coordinate coor2(2, 4);
	Coordinate coor3(0, 0);

	coor1--;
	--coor2;
	coor3 = coor1 + coor2;

	cout << coor3.m_iX << endl;
	cout << coor3.m_iY << endl;

	return 0;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!