您的位置:首页 > 其它

运算符重载

2015-12-02 22:53 211 查看

1两个问题

       在重载运算符时,通用的而且需要重点考虑的包括两个问题:

       问题一:以友元还是成员函数重载?

       问题二:返回值到底是引用还是对象?

       关于问题一,双目运算符建议以友元函数方式重载,而单目运算符是以成员函数方式重载。例如,[]、!、=、+=等单目运算符以成员函数方式重载。而+、-、*、/等双目运算符以友元函数方式重载。因为对于双目运算符,如对string对象的加法,如s2=”abc”+s1,以友元函数重载时由于有两个参数,字符串“abc”可以转换为string对象,从而调用对应的重载函数,而如果是以成员函数重载时,编译器会转换为”abc”operator+
,没办法调用对对应的成员函数。还有比较特殊的是转换运算符只能以成员函数方式重载,而流运算符只能以友元函数方式重载例如 cout<<s3以友元方式重载且第一个参数是输出流,第二个参数时被输出的对象,如果以成员函数重载要求第一个参数变成对象自身不合理。另外,特别需要注意的是,当两种方式都存在时,成员函数方式重载的优先级更高。

       关于问题二,返回引用还是对象,同样取决于是否修改自身,因为对于不修改自身的,通常都会在函数内部构造一个新的局部对象,然后将临时对象返回,此时只能是返回对象,不能是该局部对象的引用[出了作用域即析构引用也随之无效]。而对于修改自身的,则建议返回引用,效率更高。虽然单目运算符都会修改自身,似乎更加贴近返回引用,但是一种单目运算符除外就是后置++。所以,判断的条件应该是“是否返回局部对象”,不能简单依靠单目或者双目区分。另外,还有一个条件是都必须建议返回引用,即有连续操作的需求,例如输入输出流,输入输出流cin和cout的定义就是一个引用,所以为支持连续操作,必须返回引用,否则cout
<< s1 << s2 在第一次输出时返回的是对象,那么第二次输出就失效了。

       其它,对于赋值类型的运算符如+=、=,必须按其逻辑来即首先删除被赋值对象自身,然后根据赋值重新构造。

 

2 程序示例

2.1 整数,重点学习后置加法

#include "Integer.h"
#include <iostream>
using namespace std;

Integer::Integer(int n) : n_(n)
{
}

Integer::~Integer()
{
}

Integer& Integer::operator ++()
{
//cout<<"Integer& Integer::operator ++()"<<endl;
++n_;
return *this;
}

//Integer& operator++(Integer& i)
//{
// //cout<<"Integer& operator++(Integer& i)"<<endl;
// ++i.n_;
// return i;
//}

Integer Integer::operator++(int n)
{
//cout<<"Integer& Integer::operator ++()"<<endl;
//n_++;
Integer tmp(n_);
n_++;
return tmp;
}

//Integer operator++(Integer& i, int n)
//{
// Integer tmp(i.n_);
// i.n_++;
// return tmp;
//}

void Integer::Display() const
{
cout<<n_<<endl;
}

2.2 字符串

#pragma warning(disable:4996)
#include "String.h"
#include <string.h>
//#include <iostream>
//using namespace std;

String::String(const char* str)
{
str_ = AllocAndCpy(str);
}

String::String(const String& other)
{
str_ = AllocAndCpy(other.str_);
}

String& String::operator=(const String& other)
{
if (this == &other)
return *this;

return Assign(other.str_);
}

String& String::operator=(const char* str)
{
return Assign(str);
}

String& String::Assign(const char* str)
{
delete[] str_;
str_ = AllocAndCpy(str);
return *this;
}

bool String::operator!() const
{
return strlen(str_) != 0;
}

char& String::operator[](unsigned int index)
{
//return str_[index];
//non const 版本调用 const版本

return const_cast<char&>(static_cast<const String&>(*this)[index]);
}

const char& String::operator[](unsigned int index) const
{
return str_[index];
}

String::~String()
{
delete[] str_;
}

char* String::AllocAndCpy(const char* str)
{
int len = strlen(str) + 1;
char* newstr = new char[len];
memset(newstr, 0, len);
strcpy(newstr, str);

return newstr;
}

void String::Display() const
{
cout<<str_<<endl;
}

String operator+(const String& s1, const String& s2)
{
//int len = strlen(s1.str_) + strlen(s2.str_) + 1;
//char* newstr = new char[len];
//memset(newstr, 0, len);
//strcpy(newstr, s1.str_);
//strcat(newstr, s2.str_);
//
//String tmp(newstr);
//delete newstr;
String str = s1;
str += s2;
return str;
}

String& String::operator+=(const String& other)
{
int len = strlen(str_) + strlen(other.str_) + 1;
char* newstr = new char[len];
memset(newstr, 0, len);
strcpy(newstr, str_);
strcat(newstr, other.str_);

delete[] str_;

str_ = newstr;
return *this;
}

ostream& operator<<(ostream& os, const String& str)
{
os<<str.str_;
return os;
}

istream& operator>>(istream& is, String& str)
{
char tmp[1024];
cin>>tmp;
str = tmp;
return is;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: