误认为重载了某个运算符,比如+,就自动加载了与它相关的运算符,如+=,将导致错误。
如果要重载(),[],->或者任何赋值运算符,运算符重载函数必须声明为类的成员函数。对于其他运算符,运算符重载函数可以是类成员函数或者全局函数。当运算符函数作为成员函数来实现时,最左边的操作数必须是运算符的一个类对象(或者是对该类对象的一个引用)。如果左操作数必须是一个不同类对象或者一个基本类型对象时,那么该运算符必须用全局函数来实现。
流插入运算符和流提取运算符作为全局函数来重载。
拷贝构造函数的参数应该是一个const引用,以允许复制const对象
请注意,拷贝构造函数必须按引用接收参数,而非按值。否则,拷贝构造函数的调用会导致无穷递归。如果拷贝构造函数只是把源对象指针复制到目标对象指针,那么两个对象就会指向同一块动态分配的内存
使用成员函数调用 dl.operator++();
使用全局函数实现 operator++(dl);
重载后置的自增运算符
使用成员函数调用 dl.operator++(0);
使用全局函数实现 operator++(dl,0);
参数0是编译器用来区分以全局函数实现的前置和后置自增运算符的。后置的自增运算符按值返回对象,而前置的自增运算符按引用返回对象。
i++ :先引用后增加
++i :先增加后引用
例如:
如果要重载(),[],->或者任何赋值运算符,运算符重载函数必须声明为类的成员函数。对于其他运算符,运算符重载函数可以是类成员函数或者全局函数。当运算符函数作为成员函数来实现时,最左边的操作数必须是运算符的一个类对象(或者是对该类对象的一个引用)。如果左操作数必须是一个不同类对象或者一个基本类型对象时,那么该运算符必须用全局函数来实现。
流插入运算符和流提取运算符作为全局函数来重载。
我们可能选择全局函数重载运算符的一个原因是使运算符具有可交换性。
a)流插入和流提取运算符重载
//PhoneNumber.h
#ifndef __PHONENUMBER_H__
#define __PHONENUMBER_H__
#include <iostream>
using std::ostream;
using std::istream;
#include<string>
using std::string;
class PhoneNumber
{
friend ostream &operator<<(ostream &,const PhoneNumber &);
friend istream &operator>>(istream &,PhoneNumber &);
private:
string areaCode;
string exchange;
string line;
};
#endif
//PhoneNumber.cpp
#include<iomanip>
using std::setw;
#include "PhoneNumber.h"
//overloaded
ostream &operator<<(ostream &output,const PhoneNumber &number)
{
output << "(" << number.areaCode << ") " << number.exchange << "-" << number.line;
return output;
}
istream &operator>>(istream &input,PhoneNumber &number)
{
input.ignore(); //skip (
input>>setw(3)>>number.areaCode; //input areaCode
input.ignore(2);//skip ) and space
input>>setw(3)>>number.exchange;//input exchange
input.ignore();//skip -
input>>setw(4)>>number.line;
return input;
}
//test.cpp
void main()
{
PhoneNumber pn;
cout<<"Enter a phone number"<<endl;
cin>>pn;
cout<<"The PhoneNumber is :"<<pn<<" ,please call me!"<<endl;
cout<<"Enter two phone numbers"<<endl;
PhoneNumber pn1,pn2;
cin>>pn1>>pn2;
cout<<pn1<<pn2;
system("pause");
}
b)重载一元运算符
类的一元运算符可以重载为不带参数的非static成员函数或者带有一个参数的全局函数。全局函数的参数必须是该类的对象或者是该类对象的引用。c)重载二元运算符
二元运算符可以重载为带有一个参数的非static成员函数,或者两个参数(其中一个必须是类的对象或者类对象的引用)的全局函数。
//Array.h
#ifndef __ARRAY_H__
#define __ARRAY_H__
#include <iostream>
#include <iomanip>
using std::ostream;
using std::istream;
class Array
{
friend ostream& operator<<(ostream & output, const Array &a);
friend istream& operator>>(istream & input, Array &a);
public:
Array(int = 10);
Array(const Array &);
~Array();
int getSize() const;
const Array &operator=(const Array &);
bool operator==(const Array &)const;
bool operator!=(const Array &right)const
{
return !(*this == right);
}
int &operator[](int);
int operator[](int) const;
protected:
private:
int size;
int *ptr;
};
#endif
//Array.cpp
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
#include <iomanip>
using std::setw;
#include<cstdlib>
using std::exit;
#include "Array.h"
//默认的构造函数
Array::Array(int arraySize)
{
size = (arraySize > 0) ? arraySize : 10;
ptr = new int[size];
for (int i = 0; i<size; i++)
ptr[i] = 0;
}
//复制的构造函数
Array::Array(const Array &arrayToCopy):size(arrayToCopy.size)
{
ptr = new int[size];
for (int i=0; i<size; i++)
ptr[i] = arrayToCopy.ptr[i];
}
Array::~Array()
{
delete [] ptr;
}
int Array::getSize() const
{
return size;
}
const Array& Array::operator=(const Array &right)
{
if (&right != this) //防止自己给自己赋值
{
//如果两个大小不相等就清空array,重新分配大小,再赋值
if (size != right.size)
{
delete [] ptr;
size = right.size;
ptr = new int[size];
}
for (int i=0; i<size; i++)
ptr[i] = right.ptr[i];
}
return *this;
}
//判定两个Array是否相等
bool Array::operator==(const Array &right) const
{
if (size != right.size)
{
return false;
}
for (int i=0; i<size; i++)
{
if (ptr[i] != right.ptr[i])
{
return false;
}
}
return true;
}
//重载取第几个值的函数,加入坐标检测
int& Array::operator[](int subscript)
{
if (subscript<0 || subscript>=size)
{
cerr<<"\nError:Subscript "<<subscript<<" out of range"<<endl;
exit(1);
}
return ptr[subscript];
}
//
int Array::operator[](int subscript)const
{
if (subscript<0 || subscript>=size)
{
cerr<<"\nError:Subscript "<<subscript<<" out of range"<<endl;
exit(1);
}
return ptr[subscript];
}
ostream& operator<<(ostream& output, const Array &a)
{
int i;
for (i=0 ;i<a.size; i++)
{
output << setw(12) <<a.ptr[i];
if (i % 4 == 0)
{
output << endl;
}
}
if (a.size%4 != 0)
{
output << endl;
}
return output;
}
istream& operator>>(istream& input, Array &a)
{
for (int i = 0; i<a.size; i++)
{
input>>a.ptr[i];
}
return input;
}
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
#include "Array.h"
int main()
{
Array integers1(7);
Array integers2;
cout<<"Size of Array integer1 is "
<<integers1.getSize()
<<"\nArray after init:\n"
<<integers1;
cout<<"Size of Array integer2 is "
<<integers2.getSize()
<<"\nArray after init:\n"
<<integers2;
cout<<"\nEnter 17 integers:"<<endl;
cin>>integers1>>integers2;
cout<<"After input,the Array contain:\n"
<<"integer1:\n"<<integers1
<<"integer2:\n"<<integers2;
if (integers1 != integers2)
{
cout<<"integer1 and integer2 are not equal!"<<endl;
}
Array integers3(integers1);
cout<<"Size of Array integer3 is "
<<integers3.getSize()
<<"\nArray after init:\n"
<<integers3;
cout<<"Assigning integer2 to integer1"<<endl;
integers1 = integers2;
cout<<"integer1:\n"<<integers1
<<"integer2:\n"<<integers2;
if (integers1 == integers2)
{
cout<<"integer1 and integer2 are equal!"<<endl;
}
cout<<"integers1[5] is "<<integers1[5]<<endl;
cout<<"Assigning 1000 to integers1[5]"<<endl;
integers1[5] = 1000;
cout<<"integers1:\n"<<integers1;
cout<<"Attempt to assign 1000 to integers1[14]"<<endl;
integers1[14] = 1000;
system("pause");
return 0;
}
拷贝构造函数的参数应该是一个const引用,以允许复制const对象
请注意,拷贝构造函数必须按引用接收参数,而非按值。否则,拷贝构造函数的调用会导致无穷递归。如果拷贝构造函数只是把源对象指针复制到目标对象指针,那么两个对象就会指向同一块动态分配的内存
d)重载++ 和 --运算符重载
重载前置的自增运算符使用成员函数调用 dl.operator++();
使用全局函数实现 operator++(dl);
重载后置的自增运算符
使用成员函数调用 dl.operator++(0);
使用全局函数实现 operator++(dl,0);
参数0是编译器用来区分以全局函数实现的前置和后置自增运算符的。后置的自增运算符按值返回对象,而前置的自增运算符按引用返回对象。
i++ :先引用后增加
++i :先增加后引用
例如:
++Date
Data &Date::operator++()
{
operIncr();//一些操作,自增
return *this;
}
Date++
Data Date::operator++(int)
{
Date tmp = *this;
operIncr();//一些操作,自增
return tmp;
}
//这里不返回tmp的引用,是因为局部变量在声明所在的函数退出时便销毁了。