运算符重载
这一周的内容主要讲运算符重载, 但是如何设计返回值类型,以及是否需要采用成员函数都是很重要的。
1. 赋值运算符重载
T & operator=(T &a);
与copy constructor类类似, 但是存在返回值.
(1) 成员函数:只能定义成成员函数。
(2)返回值:而且返回值类型必须是引用,才能符合我们对等号的直观理解。(a = b) = c 还会将a改变, 所以我们需要返回T&。
(3)类内存在指针时需要注意如果右边赋值和本身相同时,不需要重新赋值; 而且如果原来为空指针,那么也可以直接赋值, 以上两种类型都需要先判断,以防delete时出现错误.
2. 运算符重载位友元函数
T operator+(const T &a, const T &b)
如果我们把函数重载为外部函数, 那么在内部设置为友元函数可以访问成员的私有member.
3. 流输入,输出函数
输出:
ostream & operator<< (ostream &os, const T & a);
(1)返回类型: &ostream, (保证流的一致性)
(2)外部重载函数, 因为我们需要 ostream << , 如果设置为内部函数则无法调用.
输入函数类似.
4. ++ ,--
前置++T: T operator++()
后置T++: T operator++(int)
所以下面用了国外一门课的例子.
例子MyString
#MyString.h
#ifndef __MYSTRING_H__
#define __MYSTRING_H__
#include <iostream>
using namespace std;
class MyString {
public:
// default constructor
MyString();
// constructor
MyString(const char* p);
// destructor
~MyString();
// copy constructor
MyString(const MyString& s);
// copy assignment
MyString& operator=(const MyString& s);
// returns the length of the string
int length() const { return len; }
friend int operator==(const MyString& s1,const MyString& s2);
friend int operator!=(const MyString& s1,const MyString& s2);
friend int operator>(const MyString& s1,const MyString& s2);
friend int operator<(const MyString& s1,const MyString& s2);
friend int operator>=(const MyString& s1,const MyString& s2);
friend int operator<=(const MyString& s1,const MyString& s2);
MyString& operator+=(const MyString &s);
// put-to operator
friend ostream& operator<<(ostream& os, const MyString& s);
// get-from operator
friend istream& operator>>(istream& is, MyString& s);
// operator[]
char& operator[](int i);
// operator[] const
const char& operator[](int i) const;
private:
char* data;
int len;
};
MyString operator+(const MyString& s1, const MyString& s2);
#endif
#MyString.cpp
#include <cstring>
#include <cstdio>
#include "mystring.h"
// default constructor
MyString::MyString()
{
data = new char[1];
data[0] = '\0';
len = 0;
}
// constructor
MyString::MyString(const char* p)
{
if (p) {
len = strlen(p);
data = new char[len+1];
strcpy(data, p);
} else {
data = new char[1];
data[0] = '\0';
len = 0;
}
}
// destructor
MyString::~MyString()
{
delete[] data;
}
// copy constructor
MyString::MyString(const MyString& s)
{
len = s.len;
data = new char[len+1];
strcpy(data, s.data);
}
// copy assignment
MyString& MyString::operator=(const MyString& rhs)
{
#ifdef BASIC4TRACE
fprintf(stderr, "BASIC4TRACE: (%p)->op=(const MyString&)\n", this);
#endif
if (this == rhs) {
return *this;
}
// first, deallocate memory that 'this' used to hold
delete[] data;
// now copy from rhs
len = rhs.len;
data = new char[len+1];
strcpy(data, rhs.data);
return *this;
}
//+=operator
MyString& MyString::operator+=(const MyString &s)
{
len = len + s.len;
char *temp = new char[len+1];
strcpy(temp,data);
strcat(temp,s.data);
delete[] data;
data = temp;
return *this;
}
// operator+
MyString operator+(const MyString& s1, const MyString& s2)
{
#ifdef BASIC4TRACE
fprintf(stderr,
"BASIC4TRACE: op+(const MyString&, const MyString&)\n");
#endif
MyString temp = s1;
temp += s2;
return temp;
}
// put-to operator
ostream& operator<<(ostream& os, const MyString& s)
{
os << s.data;
return os;
}
// get-from operator
istream& operator>>(istream& is, MyString& s)
{
// this is kinda cheating, but this is just to illustrate how this
// function can work.
string temp;
is >> temp;
delete[] s.data;
s.len = strlen(temp.c_str());
s.data = new char[s.len+1];
strcpy(s.data, temp.c_str());
return is;
}
// operator[] - in real life this function should be declared inline
char& MyString::operator[](int i)
{
return data[i];
}
// operator[] const - in real life this should be inline
const char& MyString::operator[](int i) const
{
// illustration of casting away constness
return ((MyString&)*this)[i];
}
int operator==(const MyString& s1,const MyString& s2)
{
return (strcmp(s1.data,s2.data)==0);
}
int operator!=(const MyString& s1, const MyString& s2)
{
return (strcmp(s1.data,s2.data)!=0);
}
int operator<(const MyString& s1,const MyString& s2)
{
return (strcmp(s1.data,s2.data)<0);
}
int operator>(const MyString& s1,const MyString& s2)
{
return(strcmp(s1.data,s2.data)>0);
}
int operator<=(const MyString& s1,const MyString& s2)
{
return(strcmp(s1.data,s2.data)<=0);
}
int operator>=(const MyString& s1,const MyString& s2)
{
return(strcmp(s1.data,s2.data)>=0);
}