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

来源:互联网 发布:淘宝店铺收藏链接生成 编辑:程序博客网 时间:2024/05/22 05:14

  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;}
运行结果如下:


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


 

0 0
原创粉丝点击