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;
}
运行结果如下:
上面的测试程序只是简单实现了大多运算符的重载方法。