类与对象——C++重载运算符

加号运算符重载

class Person
{
public:
    int mem_a;
    int mem_b;
    
//1、通过成员函数重载+号
/*
#include<iostream>
using namespace std;
class Person
{
public:
    int mem_a;
    int mem_b;
    
//1、通过成员函数重载+号
/*
Person operator +(Person &p)
{
    Person sum;
    sum.mem_a = this->mem_a + p.mem_a;
    sum.mem_b = this->mem_b + p.mem_b;
    return sum;
    //返回类型不能是引用,因为不能返回局部变量的引用
}

调用形式
Person p3 = p1.operator+(p2);
或者 p3 = p1 + p2;
*/
};

Person operator +(Person &p1,Person &p2)
{
    Person sum;
    sum.mem_a = p1.mem_a + p2.mem_a;
    sum.mem_b = p1.mem_b + p2.mem_b;
    return sum;
}


int main(){
    Person p1;
    p1.mem_a = 10;
    p1.mem_b = 10;
    Person p2;
    p2.mem_a = 10;
    p2.mem_b = 10;
    
    Person p3;
    p3 = p1 + p2;
	cout<<p3.mem_a<<p3.mem_b;
    return 0;   
}

一般情况下,我们把算术运算符定义成非成员函数,因为我们不需要改变运算对象的状态,所以形参都是常量的引用。

重载输出运算符

  1. 重载输出运算符函数不能是成员函数,因为不能实现<<在左边。 例如 p<<cout 是不可行的。
  2. 通常情况下,输出运算符的第一个形参是一个非常量ostream对象的引用。它是非常量是因为向流写入内容会改变其状态;而该对象是引用是因为我们不能直接复制一个ostream对象。
  3. 第二个形参一般是一个常量(想打印的类类型)的引用。是引用的原因是为了避免复制实参;而之所以形参可以是常量是因为打印内容一般不会改变对象的内容。
  4. operator<<返回类型一般要返回它的ostream引用(如果返回类型是void的话,cout<<x<<endl中第二个<<就会无效。)
#include<iostream>
using namespace std;
class Person
{
public:
    Person() = default;
    Person(int a,int b)
    {
        this->mem_a = a;
        this->mem_b = b;
    }
friend ostream &operator<<(ostream &os,const Person &p);
private:
    int mem_a;
    int mem_b;
};

ostream &operator<<(ostream &os,const Person &p)
{
	os << "a: "<<p.mem_a <<" b: "<<p.mem_b;
	return os;  
}
int main(){
    Person p1(10,10);
    cout << p1 << endl;
    return 0;   
}

一般输出运算符与友元搭配可实现自定义数据类型。

输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符。

前置/后置 递增递减运算符

#include<iostream>
using namespace std;
class Myclock
{
public:
    Myclock()
	{
		this->second = 0;
	}
	friend ostream &operator<<(ostream &os,const Myclock &c);
	Myclock& operator++();
	Myclock operator++(int);
	Myclock& operator--();
	Myclock operator--(int);
private:
    int second;
};

Myclock& Myclock::operator++() //为了跟内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
{
	++second;
	return *this;
}

Myclock Myclock::operator++(int) 
{
	Myclock clock = *this;
	++this->second;
	return clock;
}

Myclock& Myclock::operator--() //为了跟内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
{
	--second;
	return *this;
}

Myclock Myclock::operator--(int) //为了跟内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
{
	Myclock clock = *this;
	--this->second;
	return clock;
}
ostream &operator<<(ostream &os,const Myclock &c)
{
	os << "second: "<<c.second;
	return os;  
}
int main(){
    Myclock p1;
	int a = 10,b = 10;
	cout<< ++++a << ++++++b << endl;
	cout<<p1<<endl;
	cout<<p1++<<endl;
	cout<<p1<<endl;
	cout<<++p1<<endl;
	cout<<--p1<<endl;
	cout<<p1--<<endl; 
    return 0;   
}
  1. 最好将递增递减运算符设定为成员函数,因为它们改变的正好是所操作对象的状态。
  2. 在参数列表里使用int这一占位参数来区分前置、后置递增递减运算符。
  3. 为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的是值而不是引用(不能返回局部变量的引用。)

显式地调用后置运算符

Myclock c;
c.operator++(0);//调用后置版本的operator++;
c.operator--(); //调用前置版本的operator++;

重载赋值运算符

  1. 我们可以重载赋值运算符。不论形参的类型是什么,赋值运算符都必须定义成员函数,并且返回左侧运算对象的引用。
  2. 当类包含有指针数据成员时,合成赋值运算符函数常会引发“指针悬挂”问题。
#include <iostream>
#include<cstring>
using namespace std;
class String {
	char *ptr;
	int n;
public:
	String(char * s, int a) {
		ptr = new char[strlen(s) + 1];
		strcpy(ptr, s);
		n = a;
	}
	~String()
    {
        delete ptr; 
    }
	void print() { cout << ptr << endl; }
	String& operator=(const String& s);
};
String& String::operator=(const String& s) {
	if (this == &s)  return *this;//如果是同一对象/引用 如s1(s1);
	delete ptr;//原来的ptr字符串容纳长度可能偏小,所以需要delete
	ptr = new char[strlen(s.ptr) + 1];
	strcpy(ptr, s.ptr);
	n=s.n;
	return *this;
}
int main() {
	String p1("Hello", 8);						//L1
	{	String p2("chong qing", 10);      			//L2
        p2 = p1;							//L3
        cout << "p2:";							//L4
        p2.print();							//L5
	}								//L6    
	cout << "p1:";							//L7 
	p1.print();							//L8
}

重载复合赋值运算符

//复合赋值运算符也应该返回左侧运算对象的引用,最好是成员函数
Person& operator+=(const Person &p2)
{
    mem_a += p2.mem_a;
    mem_b += p2.mem_b;
    return *this;
}

关系运算符重载

//在如下给定的代码中,为 MyCircle 类添加关系运算符 >、<、>=、<=、==、!= ,实现按照半径对 MyCircle 对象进行比较。
//类内声明
bool operator >(const MyCircle &m1);
bool operator<(const MyCircle &m1 );
bool operator>=(const MyCircle &m1);
bool operator<=(const MyCircle &m1);
bool operator==(const MyCircle &m1);
bool operator!=(const MyCircle &m1);
	
bool MyCircle::operator>(const MyCircle &m1)
{
	if(this->radius_>m1.radius_)
	return true;
	else 
	return false;
}

bool MyCircle::operator<(const MyCircle &m1)
{
	if(this->radius_<m1.radius_)
	return true;
	else 
	return false;
}

bool MyCircle::operator >=(const MyCircle &m1)
{
	if(this->radius_ >= m1.radius_)
	return true;
	else 
	return false;
}

bool MyCircle::operator <=(const MyCircle &m1)
{
	if(this->radius_ <= m1.radius_)
	return true;
	else 
	return false;
}

bool MyCircle::operator ==(const MyCircle &m1)
{
	return this->radius_ == m1.radius_;
}

bool MyCircle::operator !=(const MyCircle &m1)
{
	return !(this->radius_ == m1.radius_);
}

int main() {
  int r1 , r2 , r3 = 0;
  cin >> r1 >> r2 >> r3;
  MyCircle c1 , c2 , c3;
  c1.setRadius(r1);
  c2.setRadius(r2);
  c3.setRadius(r3);
  cout << (c1 > c2) << endl;
  cout << (c1 < c2) << endl;
  cout << (c2 >= c3) << endl;
  cout << (c2 <= c3) << endl;
  cout << (c1 == c3) << endl;
  cout << (c1 != c3) << endl;
  return 0;
}

/* 输出:
0
1
1
0
0
1
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

highlight2333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值