@当运算符重载比完成相同工作的函数调用使程序更清晰的时候,请使用运算符重载。
@必须使用非static函数重载运算符,因为运算符必须基于对象调用,而static函数不基于任何类。
@除了“=”,“,”和“&”外,想要在类的对象上使用运算符,必须重载。“=”在对含有指针的成员进行赋值时很危险,所以对此类也要重载。
@重载不能改变运算符的优先级、结合律和元数(操作对象的个数)。
@“.” “::” “?:” “.*”四个不能重载。
@运算符函数的参数至少一个必须是用户自定义类型的对象或引用。
@运算符重载不能改变运算符对于基本类型对象的含义。
@重载了某个运算符并不意味着自动重载预与其相关的运算符,例如重载了“=”,“+=”并不自动重载。
@如果要重载“()” “[]" "->"或者任何赋值运算符,函数必须是成员函数,其他的既可以是成员函数,也可以是全局函数。
重载“>>"和"<<"。
#ifndef PHONENUBER_H
#define PHONENUBER_H
using namespace std;
class PhoneNumber
{
friend ostream& operator<<(ostream&, const PhoneNumber&);
friend istream& operator>>(istream&, PhoneNumber&);
private:
string areaCode;
string exchange;
string line;
}
#endif
#include<iomanip>
#include"PhoneNumber.h"
using namespace std;
ostream& operator<<(ostream& output, const PhoneNumber& number)
{
output<<"("<<number.areaCode<<")"<<number.exchange<<"-"<<number.line;
return output;
}
istream& operator>>(istream& input,PhoneNumber& number)
{
input.ignore();
input>>setw(3)>>number.areaCode;
input.ignore(2);
input>>setw(3)>>number.exchange;
input>>setw(4)>>number.line;
return input;
}
#include<iostream>
#include"PhoneNumber.h"
using namespace std;
int main()
{
PhoneNumber phone;
cout<<"Enter phone number in the form(123) 456_7890:"<<endl;
cin>>phone;
cout<<"The phone number entered was:";
cout<<phone<<endl;
}
@类的一元运算符可以重载为不带参数的非static成员函数或者带有一个参数的全局函数,全局函数的参数必须是该类的对象或者该类对象的引用。
@二元运算符可以重载为带有一个参数的非static成员函数,或者两个参数的全局函数。
@可以使用new和delete来动态申请和释放内存(动态存储区:堆),注意不使用的内存空间要及时释放,否则会导致内存泄漏。
@动态内存的初始化:double ×ptr = new double(123.01); Time *timePtr = new Time(12, 45 ,0);
@使用new[]动态分配数组,int *gradesArray=new int[10];不可以用int gradesArray[]=new int[10];删除:delete[] gradesArray;
@复制构造函数必须按引用接受参数,而不能按值,因为按值时会生成副本,又一次调用。类的复制构造函数。。会导致无穷递归。
@如果复制构造函数只是把源对象中的指针复制到目标对象的指针,第一个执行的析构函数会删除这个动态内存区,那么可能会导致虚悬指针。
练习:重载"<<“ ”>>" “!=" "==" "="和"[]"运算符,使的两个同类型和大小数组之间能够在不传递数组大小的情况下,进行相等比较,彼此赋值(使用动态内存申请和释放)
#ifndef ARRAY_H
#define ARRAY_H
#include<iostream>
using namespace std;
class Array
{
friend istream& operator>>(istream&, Array&);
friend ostream& operator<<(ostream&, const Array&);
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;
private:
int size;
int *ptr;
};
#include<iostream>
#include<iomanip>
#include<stdlib>
#include"Array.h"
using namespace std;
Array::Array(int arraySize)
{
size=(arraySize>0?arraySize:10);
ptr= new int[arraySize];
for(int i=0;i<arraySize;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.[i];
}
~Array::Array()
{
delete []ptr;
}
int Array::getSize()
{
return size;
}
const Array& Array::operator=(const Array& right)
{
if(&right!=this)
{
if(size!=right.size)
{
delete []ptr;
size =right.size;
ptr=new int[size];
}
for(int i=0;i<size;i++)
ptr[i]=right.[i];
}
return *this;
}
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<=||subscript>=size)
{
cout<<"\n Error subscript:"<<subscript<<" out of range"<<endl;
exit(1);
}
return ptr[subscript];
}
int Array::operator[](int subscript)const
{
if(subscript<=||subscript>=size)
{
cout<<"\n Error subscript:"<<subscript<<" out of range"<<endl;
exit(1);
}
return ptr[subscript];
}
istream& operator>>(istream& input,Array& a)
{
for(int i=0;i<a.size;i++)
input>>a.ptr[i];
return input;
}
ostream& operator<<(ostream& output,const Array& a)
{
int i;
for(int i=0;i<a.size;i++)
{
output<<setw(12)<<a.pur[i];
if((i+1)%4==0)
output<<endl;
}
if(i%4!=0)
output<<endl;
return output;
}
#include<iostream>
#include<iomanip>
#include"Array.h"
using namespace std;
int main()
{
Array integer1(7);
Array integer2;
cout<<"Size of array integer1 is "<<integer1.getSize()<<"\nArray after initialization:\n"<<integer1;
cout<<"Size of array integer2 is "<<integer2.getSize()<<"\nArray after initialization:\n"<<integer2;
cou<<"\nEnter 17 numbers:";
cin>>integer1>>integer2;
cout<<"\nAfter input, the Arrays contain:\n"
<<"integer1:\n"<<integer1;
<<"integer2:\n"<<integer2;
cout<<"\nEvaluating:integer1!=integer2"<<endl;
if(integer1!=integer2)
cout<<"integer1 and integer2 are not equal"<<endl;
Array integer3(integer1);
cout<<"\nSize of Array integer3 is "<<integer3.getSize()<<"\nArray after initializing\n"<<integer3;
cout<<"\n Assigning integer2 to integer1:"<<endl;
integer1=integer2;
cout<<"integer1:"<<integer1<<"integer2:"<<integer2;
cout<<"\nEvaluating:integer1==integer2"<<endl;
if(integer1==integer2)
cout<<"integer1 and integer2 are equal"<<endl;
cout<<"\ninteger[5] is "<<integers1[5];
cout<<"\n\nAssinging 1000 to integer1[5]"<<endl;
integer[5]=1000;
cout<<"integer1 is:\n"<<integer1;
cout<<"Attempt t assign 1000 to integer1[15]"<<endl;
integer1[15]=1000;
}
@强制类型转换可以在普通类型之间转换,对于自定义类型呢?需要自己构造转换构造函数,用于将某一类的对象转换成特定类的对象的单参数构造函数。
@这类转换必须是非static成员函数。
@A:: operator char*() const;将A的对象转换成临时的char×对象。注意声明为const以及没有指定返回类型的原因。
@强制类型转换运算符和构造函数的优点之一是:必要时,编译器可以隐式地调用这些函数来创建临时的对象。