C++笔记——运算符重载

  C++定义了大量的运算符以及内置类型转换规则。当这些运算符被用于类类型的对象时,C++允许程序员为相应的运算符指定新的含义。同时也可以自定义类类型之间的转换规则。

 当运算符作用于类类型对象时,可以通过运算符重载来重新定义该运算符的含义。合理的使用运算符重载,可以使我们的程序更易于编写和阅读。

 重载运算符是具有特殊名字的函数:它的名字有关键字operator+运算符共同组成。和其他函数类似,重载的运算符也包含返回类型、参数列表和函数体。

 重载运算符函数的参数数量和该运算符作用的运算对象数量一样多。医院运算符有一个参数,二元运算符有两个对象。对于二元运算符,左侧运算对象传递给第一个参数,而右侧运算对象传递给第二个参数。

 如果重载的运算符函数是成员函数,则它的左侧运算对象呗绑定到隐式的this指针上。因此,成员运算符重载函数的参数数量比运算符的运算对象少一个。

 注意:当一个运算符重载函数是成员函数时,this指针绑定到左侧运算对象。

 对于一个运算符重载函数,它或者是类的成员,或者至少包含一个类类型的参数。如下的声明就是错误的:

  int operator+(int,int)

 不能为int重定义内置的运算符。

 这意味着运算符作用于内置类型的运算对象时,我们不能改变改运算符的含义。

 我们可以重载大多数的运算符,具体如下图:

 

 对于一个重载的运算符来说。重载运算符不会改变该运算符原有的优先级和结合律。

 作为调用运算符重载函数,既可以运算符作用于类型正确的实参,以间接的方式来调用,也可以像普通函数调用一样直接调用运算符重载函数。如下两种方式都正确:

  tmp1 + tmp2;  //普通的表达式

  operator+(tmp1,tmp2);  //等价的函数调用

 通常情况下,不能重载逗号,取地址,逻辑与,逻辑或运算符。

 在做运算符重载的时候,程序员首先要考虑是将其作为成员函数,还是作为普通函数。有的情况下。我们不得不将其作为成员函数。而又的情况下,其作为普通函数比成员函数更好。

 下面的原则,有助于程序员决定将其作为成员函数还是普通的非成员函数:

 1、赋值(=)、下标([])、调用(())和成员访问箭头(->)运算符必须是成员函数;

 2、复合赋值运算符一般应该是成员函数,但并非必须。

 3、改变对象状态的运算符或者与给定类型密切相关的运算符,如递增、递减和解引用云散浮,通常应该是成员函数

 当把运算符重载函数定义为成员函数时,它的左侧运算对应必须是运算符所属类的一个对象。

 

 输入输出运算符重载必须是非成员函数,而不是类的成员函数。否则他们的左侧运算对象将是我们类的一个对象。

因为程序员无法给标准输入输出添加任何成员。所以将其定义成非成员函数。而且经常会在输入输出运算符重载函数中访问类的私有成员,所以输入输出运算符重载函数一般被声明为友元函数。

 下面例子重载了大多运算符:

MyString.h定义MyString类

#ifndef __MY_STRING_H_
#define __MY_STRING_H_

#include <string>

class MyString
{
public:
	MyString();
	MyString(const char* str);
	MyString(const MyString& obj);
	MyString(unsigned len);

	unsigned size();
	MyString& operator=(const MyString& str);
	friend std::ostream& operator<<(std::ostream& out,const MyString& str);
	friend std::istream& operator>>(std::istream& in,MyString& str);
	char& operator[](unsigned index);
	MyString operator+(const MyString& str);
	MyString& operator+=(const MyString& str);

	~MyString();
private:
	char * m_str;
	unsigned m_len;
};

#endif
MyString.cpp实现类的相关成员和非成员函数:

#include <iostream>
#include "MyString.h"

MyString::MyString()   //定义默认构造函数
{
	std::cout<<"MyString()"<<std::endl;
	m_str = new char[1];
	m_str[0] = '\0';
	m_len = 1;
}

MyString::MyString(const char* str)   //字符串构造函数
{
	std::cout<<"MyString(const char* str)"<<std::endl;
	if(str == NULL)
		return;
	
	m_len = strlen(str) + 1;
	m_str = new char[m_len];

	strcpy(m_str,str);
	m_str[m_len-1] = '\0';
}

MyString::MyString(const MyString& obj)  //拷贝构造函数
{
	std::cout<<"MyString(const MyString& obj)"<<std::endl;

	m_len = strlen(obj.m_str) + 1;
	m_str = new char[m_len];

	strcpy(m_str,obj.m_str);
	m_str[m_len-1] = '\0';
}

MyString::MyString(unsigned len)  //根据len构造函数
{
	m_len = len + 1;
	m_str = new char[m_len];
	m_str[1] = '\0';
}

MyString::~MyString()  //西沟函数
{
	std::cout<<"~MyString()"<<std::endl;
	if(m_str != NULL)
		delete[] m_str;
}

unsigned MyString::size()   //求长度
{
	return m_len;
}

MyString& MyString::operator=(const MyString& str)   //赋值运算符重载
{
	std::cout<<"MyString::operator="<<std::endl;
	if(m_str != NULL)
		delete[] m_str;

	m_len = strlen(str.m_str) + 1;
	m_str = new char[m_len];

	strcpy(m_str,str.m_str);
	m_str[m_len-1] = '\0';
	return *this;
}

std::ostream& operator<<(std::ostream& out,const MyString& str)  //输出运算符重载
{
	out<<"str:"<<str.m_str<<"\tm_len:"<<str.m_len;
	return out;
}

std::istream& operator>>(std::istream& in,MyString& str)   //输入运算符重载
{
	std::cout<<"please input a str:";
	std::string temp;
	in>>temp;
	if(in)
	{
		if(str.m_len < temp.size())
		{
			delete[] str.m_str;
			str.m_len = temp.size() + 1;
			str.m_str = new char[str.m_len];

			strcpy(str.m_str,temp.c_str());
			str.m_str[str.m_len-1] = '\0';
		}else
		{
			strcpy(str.m_str,temp.c_str());
		}
	}/*else
	{
		str.m_str[0] = '\0';
		str.m_len = 0;
	}*/
	return in;
}

char& MyString::operator[](unsigned index)   //下标运算符重载
{
	return m_str[index];
}

MyString MyString::operator+(const MyString& str)  //加法运算符重载
{
	MyString temp;

	temp.m_len = m_len + str.m_len - 1;
	temp.m_str = new char[temp.m_len];

	strcpy(temp.m_str,m_str);
	strcpy(temp.m_str+m_len - 1,str.m_str);

	return temp;
}

MyString& MyString::operator+=(const MyString& str)   //符合加法运算符重载
{
	std::string t_str = m_str;
	unsigned len = m_len;

	delete[] m_str;

	m_str = new char[len + str.m_len - 1];
	m_len += str.m_len - 1;

	strcpy(m_str,t_str.c_str());
	strcpy(m_str+len - 1,str.m_str);

	return *this;
}
test.cpp测试类:

#include <iostream>
#include "MyString.h"

using namespace std;

void test1()
{
	MyString str1("caonima");
	MyString str2("caocaocao");
	MyString str4(str2);
	cout<<str2<<endl;
	//str1 = str2;
	cout<<str1<<endl;
/*	MyString str3(10);
	cin>>str3;
	cout<<str3<<endl;

	str3[0] = 'd';
	cout<<str3<<endl;*/

	MyString str3;
	str3 = str1 + str2;
	cout<<str3<<endl;

	str3 += str1;
	cout<<str3<<endl;
}

int main()
{
	test1();
	return 0;
}
运行结果如下:


 上面的测试程序只是简单实现了大多运算符的重载方法。


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值