ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++学习笔记(6)

2022-02-25 21:05:08  阅读:150  来源: 互联网

标签:运算符 return int 笔记 学习 operator num C++ 重载


目录

一.什么是运算符重载

二.运算符重载的方式

1.友元重载

2.类成员函数重载

三.特殊运算符重载

1.流运算符

2.自增自减运算符重载及文本重载

(1)自增自减

(2)文本重载

(3)类的隐式转换  

 四.运算符重载案例

1.手写动态数组

2.包装一下int

3.其他重载


一.什么是运算符重载

运算符重载就是赋予运算符具有操作自定义类型数据的功能。它的本质上就是函数的调用

运算符重载函数的构成:

函数返回值:由运算后完成的值决定。函数名:operator加上想要重载的运算符。参数:由运算符的操作数以及重载方式决定。

二.运算符重载的方式

1.友元重载

用友元的方式实现运算符重载,其函数参数的个数就是运算符的操作数。我们以实现 “+” 为例子:

class Complex
{
public:
	Complex(int a,int b):a(a),b(b){}
	void print()
	{
		cout << a << " " << b << endl;
	}
	friend Complex operator+(Complex one, Complex two)
	{
		return Complex(one.a + two.a, one.b + two.b);
	}
protected:
	int a;
	int b;
};
int main()
{
	Complex a(1, 1);
	Complex b(2, 0);
	Complex c = a + b;
	c.print();
}

注意,我们看到的 “c = a + b” 是运算符重载的隐式调用,显式调用如下:

Complex c = operator+(a, b);

其实跟普通函数没啥区别。

2.类成员函数重载

用类成员函数的方式实现运算符重载,参数个数等于运算符操作数-1,因为类成员函数本质上是类里的东西,需要用对象来调用,所以参数自然少了一个。我们以实现 “>” 为例子:

bool operator>(Complex object)
{
	if (this->a > object.a) return true;
	else if (this->a == object.a && this->b > object.b) return true;
	else return false;
}

这样就可以进行对象的比较了。

三.特殊运算符重载

1.流运算符

cin类型:istream类的对象。

cout类型:ostream类的对象。

流运算符:“<<” ,“>>”。

friend void operator>>(istream& in, A& a)
{
	in >> a.name >> a.age;
}
friend void operator<<(ostream& out, A& a)
{
	out << a.name << '\t' << a.age << endl;
}

按照上面的写法我们可以实现输入和输出我们定义的类A,但这种实现是有局限的,因为返回的是void类型,所以不能做连续输入和输出,那这个要怎么优化呢?

class A
{
public:
	A(string name = "", int age = 10) :name(name), age(age) {}

	friend istream& operator>>(istream& in, A& a)
	{
		in >> a.name >> a.age;
		cout << endl;
		return in;
	}
	friend ostream& operator<<(ostream& out, A& a)
	{
		out << a.name << '\t' << a.age << endl;
		return out;
	}
protected:
	string name;
	int age;
};
int main()
{
	A a("小蓝", 18);
	A b("小绿", 19);
	A c;
	A d;
	cin >> c >> d;
	cout << a << b << c << d;
}

 如图,当我们把返回值修改成istream和ostream的引用类型时,便可以实现连续输入输出。

2.自增自减运算符重载及文本重载

(1)自增自减

自增自减运算符重载需要解决前置后置的问题,需要增加一个无用参数,以表示当前运算符是后置操作。

A operator++(int)
{
	return A(name, age++);
}	
A operator++()
{
	return A(name, ++age);
}

我们来编写一些测试案例:

class A
{
public:
	A(string name = "", int age = 10) :name(name), age(age) {}
	friend ostream& operator<<(ostream& out, A& a)
	{
		out << a.name << '\t' << a.age << endl;
		return out;
	}
	A operator++(int)
	{
		return A(name, age++);
	}
	A operator++()
	{
		return A(name, ++age);
	}
protected:
	string name;
	int age;
};
int main()
{
	A a("小蓝", 18);
	A object = a++;
	cout << object << a;
	object = ++a;
	cout << object << a;
}

 可以看到,我们实现了自定义类型的自增,自减同理。

(2)文本重载

固定的返回值类型:

unsigned long long

固定的函数名:

operator""

固定参数类型:

unsigned long long

一般要进行多次单位转换的时候,可以使用文本重载,下面给出一个换算时间的例子:

unsigned long long operator"" _h(unsigned long long num)
{
	return num * 60 * 60;
}
unsigned long long operator"" _min(unsigned long long num)
{
	return num * 60;
}
unsigned long long operator"" _s(unsigned long long num)
{
	return num;
}
int main()
{
	int second = 1_h + 10_min + 20_s;
	cout << second << "s";
}

(3)类的隐式转换  

定义一个新的对象,没办法直接把它赋值给一个基本数据类型--->1.重载运算符  2.隐式转换

class A
{
public:
	A(string name ,int age):name(name),age(age){}
	//类的对象的隐式转换  
	operator int()       
	{
		return age;       
	}
protected:
	string name;
	int age;
};
 
int main() 
{
 
	A a("a", 18);
	int age= a;    
	cout << age<< endl;
	return 0;
}

 四.运算符重载案例

1.手写动态数组

第一步:设计基础元素

class vector
{
public:
protected:
	int size;      //当前元素个数
	int* base;     //存储空间
	int capacity;  //容量
};

第二步:写构造函数和析构函数

vector(int capacity) :capacity(capacity)
{
	if (capacity > 0)
	{
		base = new int[capacity];
		this->capacity = capacity;
		this->size = 0;
	}
}
~vector()
{
	if (base)
	{
		delete[] base;
		base = nullptr;
	}
}

第三步:写两个万金油函数

bool empty() const
{
	return size == 0;
}
int getsize()const
{
	return size;
}

第四步:实现下标访问

int& operator[](int index)
{
	if (index >= 0 && index < capacity)
	{
		return base[index];
	}
}

第五步:接着实现动态数组增长

void push_back(int data)
{
	if (size == capacity)
	{
		int* newbase = new int[capacity * 2];
		this->capacity *= capacity;
		for (int i = 0; i < size; i++)
		{
			newbase[i] = base[i];
		}
		delete[] base;
		base = newbase;
	}
	base[size++] = data;
}

最后,写一些调试代码试试看!

int main()
{
	vector a(3);
	for (int i = 0; i < 5; i++)
	{
		a.push_back(i);
		cout << a[i] << " ";
	}
	cout << endl << a.getsize();
}

 可以看到,结果跟我们想要的一样!

2.包装一下int

这里比较简单,直接贴代码,代码中已经加好了注释。

class Int
{
public:
	Int(int num) :num(num) {}
	int& data() 
	{
		return num;                    //获取数据
	}
	string tostr() 
	{
		return to_string(num);         //把int转换为string类型
	}
	//算术运算符重载
	Int operator+(const Int& value)    //+ 对象相加 类中成员函数重载的方式
	{
		return Int(this->num + value.num);
	}
	//友元重载: 操作数==重载函数的参数个数
	friend Int operator-(const Int& one, const Int& two) 
	{		
		return Int(one.num - two.num);
	}
	Int operator+=(const int& value)  //原来的值+=int类型的值
	{
		return Int(this->num + value);
	}
	Int operator+=(const Int& value)  //原来的值+=一个对象 形成重载|参数类型不一致   
	{
		return Int(this->num + value.num);
	}
 
	Int operator++(int) 
	{
		return Int(this->num++);
	}
	Int operator++() 
	{
		return Int(++this->num);
	}  
    //位运算符重载
	Int operator&(const Int& value) 
	{
		return Int(this->num & value.num);
	}
	bool operator!() 
	{
		return !this->num;
	}
    //负号
	Int operator-() 
	{
		return Int(-this->num);
	}
    //流重载
	friend ostream& operator<<(ostream& out, const Int& object) 
	{
		out << object.num << endl;
		return out;
	}
	friend  istream& operator>>(istream& in, Int& object) 
	{
		in >> object.num;
		return in;
	}
    //取地址符重载
	int* operator&() 
	{
		return &this->num;  //不需要返回对象,返回int*类型的地址即可
	}
    //关系运算符重载
	bool operator>(const Int& object) 
	{
		return this->num > object.num;
	}
 
protected:
	int num;    //数据还是int类型
};

3.其他重载

重载():

class Function
{
	typedef void(*PF)();
public:
	Function(PF pf) :pf(pf){}
	void operator()()
	{
		pf();
	}
protected:
	PF pf;
};
void print()
{
	cout << "重载成功";
}
int main()
{
	Function f(print);
	f();
}

重载->:

class A
{
public:
	A(string name,int age):name(name),age(age){}
	void print()
	{
		cout << name << " " << age << endl;
	}
protected:
	string name;
	int age;
};
class Auto_ptr
{
public:
	Auto_ptr(int* ptr):ptr(ptr){}
	Auto_ptr(A* pa):pa(pa){}
	int& operator*()
	{
		return *ptr;
	}
	A* operator->()
	{
		return pa;
	}
	~Auto_ptr()
	{
		if (ptr)
		{
			delete ptr;
			ptr = nullptr;
		}
		if (pa)
		{
			delete pa;
			pa = nullptr;
		}
	}
protected:
	int* ptr;
	A* pa;
};
int main()
{
	Auto_ptr ptr(new int(18));
	cout << *ptr << endl;
	Auto_ptr ptra(new A("小蓝", 20));
	ptra->print();
}

好了,今天的学习就到这啦!

标签:运算符,return,int,笔记,学习,operator,num,C++,重载
来源: https://blog.csdn.net/m0_60958852/article/details/123137830

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有