【C++】重载运算符

目录

重载算术运算符(加减乘除 )

重载类内操作符

重载全局操作符

重载元素操作符[]

重载关系操作符

重载转换操作符()

重载输入输出操作符


重载算术运算符(加减乘除 )

重载加号运算符的形式为:

class Object
{
public:
	Object operator + (const Object& other) 
	{}
};

重载类内操作符

程序功能:实现分数的加号操作。

#include "pch.h"
#include <iostream>
#include <stdio.h>

class Fraction
{
public:
	Fraction() : num(1), den(1)
	{}
	Fraction(int n, int d) : num(n), den(d)
	{}
	Fraction operator + (const Fraction& other)
	{
		Fraction result;
		result.den = den * other.den;
		result.num = num * other.den + den * other.num;
		return result;
	}
private:
	int num;//分子
	int den;//分母
};

int main()
{
	Fraction fa(2, 3);
	Fraction fb(3, 5);
	Fraction fc = fa + fb;

	return 0;
}

注意:

(1)重载操作符的形式上像一个函数,但它不是函数;

(2)名称:operator +, 这个是固定不变的

(3)返回值:类型不变,总是为该对象的类型

(4)参数:基本上不变

(5)受public/protected/private的限制

重载全局操作符

#include "pch.h"
#include <iostream>
#include <stdio.h>

class Fraction
{
public:
	Fraction() : num(1), den(1)
	{}
	Fraction(int n, int d) : num(n), den(d)
	{}
public: //这里被声明为public不然operator +不能访问num和den
	int num;//分子
	int den;//分母
};

Fraction operator + (const Fraction& a, const Fraction& b)
{
	Fraction result;
	result.den = a.den * b.den;
	result.num = a.num * b.den + a.den * b.num;
	return result;
}

int main()
{
	Fraction fa(2, 3);
	Fraction fb(3, 5);
	Fraction fc = fa + fb;

	return 0;
}

上面强制将num和den变成了public,但是一般情况下我们都会申明为private。那如果申命为private时,就需要使用friend修饰符。具体实现如下所示:

#include "pch.h"
#include <iostream>
#include <stdio.h>

class Fraction
{
	friend Fraction operator +(const Fraction& a, const Fraction& b);
public:
	Fraction() : num(1), den(1)
	{}
	Fraction(int n, int d) : num(n), den(d)
	{}
private:
	int num;//分子
	int den;//分母
};

Fraction operator + (const Fraction& a, const Fraction& b)
{
	Fraction result;
	result.den = a.den * b.den;
	result.num = a.num * b.den + a.den * b.num;
	return result;
}

int main()
{
	Fraction fa(2, 3);
	Fraction fb(3, 5);
	Fraction fc = fa + fb;

	return 0;
}

重载元素操作符[]

重载元素操作符[]的一般形式

Element& operator [] (Type Index){}

其中,

(1)名字:operator [],是固定不变的

(2)返回值:一般应该返回一个子元素的引用,表示返回值是一个“左值”,可读可写

(3)参数:类型可以自己选择,用于指定元素的下标,不一定要使用int,使用其他类型也可以,比如char*。

[]用于访问一组元素中的一个元素。默认地,数组是支持下标访问的。

例如:

int a[5] = {1,2,3,4,5};
a[0] = 10;
int b = a[0];

当一个对象设计用于包含多个元素时,可以重载操作符[]

比如,一个字符串Text,它包含了多个元素(每个元素时一个字符)

Text txt("hello,world");
char ch = txt[0];

又比如,一个DataStore里存储了多个Student数据

DataStore ds;
Student& st = ds["nick"];

程序功能:可以使用下标访问字符串元素,并修改字符串元素。

class Text
{
public:
	Text(const char* str)
	{
		m_size = strlen(str) + 1;
		m_buf = new char[m_size];
		strcpy(m_buf, str);
	}
	~Text()
	{
		delete[] m_buf;
	}
	char& operator[] (int index)
	{
		return m_buf[index];
	}
private:
	int m_size;
	char* m_buf;
};

int main()
{
	Text m_text("hello");
	char a = m_text[0];
	m_text[0] = 'H';
	return 0;
}

程序功能:用链表实现学生数据的插入,并可通过下标来访问某个学生。

DataStore.h

#ifndef _DATASTORE_H
#define _DATASTORE_H

struct Student
{
	int id;
	char name[16];
	Student* next;
};

class DataStore
{
public:
	DataStore();
	~DataStore();
	Student& operator [](const char* name);
	void Add(const Student* data);
	Student* Find(int id);
	void Print();
public:
	static Student null_one; //这里是为了防止返回无效值而设置的一个特定值
private:
	Student m_head;
};

#endif // !_DATASTORE_H

DataStore.cpp

#include "pch.h"
#include "DataStore.h"
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static Student null_one = {-1, "null"};

DataStore::DataStore()
{
	m_head.next = {0};
}


DataStore::~DataStore()
{
	Student* p = m_head.next;
	while (p)
	{
		Student* next = p->next;
		free(p);
		p = next;
	}
}

void DataStore::Add(const Student* data)
{
	Student* copy = (Student*)malloc(sizeof(Student));
	*copy = *data;

	Student* cur = m_head.next;
	Student* pre = &m_head;
	while (cur)
	{
		if (copy->id < cur->id)
		{
			break;
		}
		pre = cur;
		cur = cur->next;
	}
	copy->next = pre->next; //obj->next = cur;
	pre->next = copy;
}

Student* DataStore::Find(int id)
{
	Student* p = m_head.next;
	while (p)
	{
		if (p->id == id)
			return p;
		p = p->next;
	}
	return null_one;
}

void DataStore::Print()
{
	Student* p = m_head.next;
	while (p)
	{
		printf("id:%d, name:%s\n", p->id, p->name);
		p = p->next;
	}
}

Student& DataStore::operator [](const char* name)
{
	Student* p = m_head.next;
	while (p)
	{
		if (strcmp(p->name, name) == 0)
		{
			return *p;
		}
		p = p->next;
	}
	return null_one;
}

main.cpp

#include "pch.h"
#include <iostream>
#include <stdio.h>
#include "DataStore.h"

int main()
{
	DataStore ds;
	Student s1 = {1, "nick"};
	ds.Add(&s1);

	Student s2 = { 2, "nancy" };
	ds.Add(&s2);

	ds.Print();

	Student stu = ds["nick"];
	if (stu.id > 0)
	{
		printf("This Object has been found.");
	}

	return 0;
}

注意:

(1)操作符[]的返回值类型为引用,才算是符合使用习惯;(毕竟又是需要作为左值而存在)

(2)元素下标的类型是不一定要用int,用char*也可以;

(3)操作符[]是可以重载的,参数类型不同;

(4)必须考虑元素不存在的情形。(就如上面代码的static Student null_one = {-1, "null"};)

重载关系操作符

关系操作符:>  <  >=  <=  ==  !=

比如下面代码就直接报错,因为自定义的类并没有实现==操作。

Fraction fa(2, 3);
Fraction fb(4, 6);
if(fa == fb) //编译报错
{
}

一般有2种写法:

(1)重载类操作符

class Object
{
public:
	bool operator == (const Object& other) {}
};

a. 名称operator ==

b. 返回值:bool

c. 参数:可以重载

(2)重载全局操作符

bool operator == (const Object& a, const Object& b) {}

接下来以重载类操作符为例

程序功能:实现分数==功能。

#include "stdafx.h"
#include "stdio.h"
#include <stdlib.h>
#include <string.h>

class Fraction
{
public:
	Fraction() : num(1), den(1)
	{}
	Fraction(int n, int d) : num(n), den(d)
	{}
	bool operator == (const Fraction& other)
	{
		if (num * other.den == den * other.num)
			return true;
		return false;
	}
public:
	int num;
	int den;
};

int main()
{
	Fraction a(2, 3);
	Fraction b(4, 6);
	if (a == b)
	{
		printf("OK.");
	}
	
    return 0;
}

结果为:

OK.

重载转换操作符()

一般形式:

class Object
{
public:
	operator Type() //Type目标类型
	{
		Type result;
		return result;
	}
};

C++允许将一个类型转换成另一个类型。比如int a = (int) 1.23; //将double转成int类型

小括号就是类型转换符,括号里的就是要转换的目标类型。

就比如上面按个分数的例子,我们可以使用()将其转换成double类型的数据。

Fraction fa(4,5);
double value = (double)fa;

但这个需要自己重写()操作符,以实现类型转换的操作。

#include "stdafx.h"
#include "stdio.h"
#include <stdlib.h>
#include <string.h>

class Fraction
{
public:
	Fraction() : num(1), den(1)
	{}
	Fraction(int n, int d) : num(n), den(d)
	{}

	operator double()
	{
		return (double)num/den; //先将num转成double,然后结果就被自动转成double
	}
public:
	int num;
	int den;
};

int main()
{
	Fraction a(2, 3);

	double c = (double)a;
	
    return 0;
}

重载输入输出操作符

C++中引入操作符 >> 表示输入,<< 表示输出

注意:在位操作符里他们承担的意思是:左移位,右移位。

在位操作中:
unsigned int a = 0xAA << 4; //左操作数为整形时,表示位移

输入输出:
Logger lg;
lg << "hello, world"; //左操作数为自定义对象,表示输入输出

一般形式:

Logger& operator << (Type value)
{
    return *this;
}

(1)名称:operator <<

(2)返回值:左值,一般返回对象自己

(3)参数:待输出的数据

程序功能:定义一个类logger,用于输出打印日志

#include "stdafx.h"
#include <stdio.h>


class Point
{
public:
	Point(int x, int y)
	{
		this->x = x;
		this->y = y;
	}
public:
	int x, y;
};

class Logger
{
public:
	Logger& operator << (int value)
	{
		printf("%d", value);
		return *this;
	}
	Logger& operator << (double value)
	{
		printf("%f", value);
		return *this;
	}
	Logger& operator << (const char* value)
	{
		printf("%s", value);
		return *this;
	}
	Logger& operator << (const Point& point)
	{
		printf("(%d,%d)", point.x, point.y);
		return *this;
	}
};


int main()
{
	Logger lg;
	Point p(1, 2);

	lg << 1 << "  hello";
	lg << p;
    return 0;
}

为什么返回左值?

习惯而已。所以只能返回引用。

猜你喜欢

转载自blog.csdn.net/u013066730/article/details/84565409
今日推荐