第五章 运算符重载本章主要内容
1,运算符重载的目的
2,运算符重载的两种形式:成员函数和友元函数
3,一元运算符的重载 —— 重点
4,二元运算符的重载 —— 重点
5,不允许重载的运算符
6,运算符重载的一般规则 —— 重点
15:06:48
– 数据类型总是与相关的运算相联系的
– 对类来说,一般情况下,调用类中提供的成员函数完成对该类的对象的操作,但对某些类来说,这种方式显得很不自然,不符合日常的思维习惯例:复数加法
class Complex{
float real,image;
public:
Complex(float r=0,float i=0);
Complex(const Complex & c);
Complex Add(const Complex & right);
};
void main(){
Complex left(1,2),right(3,4);
Complex result;
result=left.Add(right);
}
存在的问题:
复数在数学上有很规范的运算和运算符,但本类中 用成员函数而不是使用数学上的运算符 代表对复数进行的数学运算,
显得很不自然,不符合人的思维习惯改进:
对复数类提供重载的运算符
15:06:48
运算符重载通过在类中建立运算符函数 (operator function)实现声明运算符函数的一般形式为返回值类形 operator 运算符 (形参运算量列表 );
例:复数的加法
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
Complex operator +(const Complex & right);
};
void main(){
Complex left(1,2),right(3,4);
Complex result;
result = left + right;
}
15:06:48
关于运算符重载的说明
运算符重载的目的是 为了语法上的方便,使用户尽可能以符合日常思维或比较自然的方式编写程序
运算符重载的实质是改变运算符本来的含义,使对特定数据类型的数据进行这种运算时,调用该运算符对应的函数重载运算符时,该运算实现什么操作完全取决于类的设计者
(函数体由类的设计者实现 ),但一般 应参照该运算符本来的意义,否则会引起语法或使用上的混乱
运算符重载是针对 特定类的对象之间的运算 的,基本数据类型 (如 int,float等 )的变量之间进行的运算不能重载
运算符重载没有也不能改变该运算符的优先级与结合性
只能重载已存在的运算符,不能通过重载的方式创造新的运算符,也不能改变该运算符的操作数数目
运算符重载有两种形式,成元函数与友元函数
以下几个运算符不能被重载
sizeof,*(指针运算符 ),,?,
15:06:48
一元运算符的重载
一元运算本身需要一个操作数
可重载成成员函数,也可重载成友元函数
成员函数:形式上无参数,操作数即为 this指针指向的对象
友元函数:形式上带有一个参数,该参数即为操作数例:一元运算符的重载
//成员函数
class Integer{
int i;
public:
Integer(int ii=0);
void show();
Integer operator+();
Integer operator-();
};
//友元函数
class Byte{
int b;
public:
Byte(int bb=0);
void show();
friend Byte operator+(
const Byte & bt);
friend Byte operator-(
const Byte & bt);
};
15:06:48
实现
//成员函数
Integer::Integer(int ii)
{ i=ii;}
void Integer::show()
{ cout << i << endl;}
Integer Integer::operator+()
{return *this;}
Integer Integer::operator-(){
Integer temp(-i);
return temp;
}
//友元函数
Byte::Byte(int bb)
{ b=bb;}
void Byte::show()
{ cout << b << endl;}
Byte operator+(
const Byte & bt)
{return bt;}
Byte operator-(
const Byte & bt){
Byte temp(-bt.b);
return temp;
}
15:06:48
一元运算符重载的特例,++,--
++与 --有前置与后置 (即 先 ++,先 --和 后 ++,后 --)两种形式
为了区别这两种形式,重载时对应的函数形式有所不同例,Integer类
.成员函数:以 ++为例
class Integer{
int i;
public:
Integer operator++();
Integer operator++(int);
};
Integer Integer::operator ++(){
i++;
return *this;
}
Integer Integer::operator++(int)
{
Integer temp = *this;
i++;
return temp;
}
前置形式 后置形式
Integer intObj(10);
++intObj;
intObj++;
15:06:48
.友元函数
class Byte{
int b;
public:
friend Byte operator++(Byte & bt);
friend Byte operator++(Byte & bt,int);
};
Byte operator++(Byte & bt){
bt.b++;
return bt;
}
Byte operator++(Byte & bt,int){
Byte temp=bt;
bt.b++;
return temp;
}
Byte btObj(10);
++btObj;
btObj++;
前置形式后置形式
15:06:48
二元运算符的重载
二元运算本身需要两个操作数
有些二元运算符既可重载成成元函数,也可重载成友元函数
成员函数:形式上需要一个形参,此形参做为右操作数,
左操作数为 this指针指向的对象
友元函数:形式上需要两个形参,分别代表左操作数和右操作数
15:06:48
例:复数类
class Complex{
float real,image;
public:
Complex(float r=0,float i=0){real=r;image=i;}
Complex operator +(const Complex & right);
friend Complex operator -(const Complex & left,
const Complex & right);
};
Complex Complex::operator +(const Complex & right){
Complex temp(real+right.real,image+right.image);
return temp;
}
Complex operator-(const Complex& left,
const Complex& right){
Complex temp(left.real-right.real,
left.image-right.image);
return temp;
}
Complex c1(1,2),c2(3,4);
Complex c3 = c1 + c2;
Complex c4 = c1 – c2;
注意:
二元运算符重载对应的成员函数 由左操作数调用,意即
c1+c2? c1.operator+(c2)
15:06:48
二元运算符重载的特殊情况
1.重载赋值运算符,=
重载函数的原型为:
类名 & 类名,:operator=(const 类名 &);
例,Name类的重载赋值运算符
class Name{
char *pname;
int size;
public:
Name & operator=(const Name & nm){
size=nm.size;
if(nm.pname!=NULL){
pname=new char[size + 1];
strcpy(pname,nm.pname);
}
return *this;
}
};
Name nm1(―张三,),nm2(―李四,);
nm2 = nm1;
赋值运算符 必须 被重载成成员函数若类中未重载赋值运算符,该类的对象之间也可以互相赋值,但完成的是位对位 (或成员对成员 )的赋值,与浅拷贝的情况类似
15:06:48
2.重载下标运算符,[]
重载函数的原型为返回值类型名 & 类名,:opeator[](int);
3.重载函数调用运算符,()
重载函数的原型为返回值类型名 类名,:operator()(形参类型列表 );
class vector{
int *v;
int len;
public:
vector(int size=1);
vector(const vector& vct);
~ vector();
int & operator[](int i);
int operator()();
};
下标运算符和函数调用运算符 必须被重载成成员函数
15:06:48
vector类的实现
vector::vector(int size){
if(size<=0){cout << ―Error in Size‖;abort();}
v = new int [size];len = size;
}
vector::vector(const vector & vct){
len=vct.len;
if(vct.v!=NULL){
v = new int [len];
for(int i=0;i<len;i++)v[i]=vct.v[i];
}
}
vector::~ vector()
{if (v!=NULL){delete []v;len=0;}}
int & vector::operator[](int i)
{ return v[i]; }
int vector::operator()()
{ return len; }
void main(){
int k,i;
cin >> k;
vector A(k);
for(i=0;i<k;i++)A[i]=i+1;
for(i=0;i<k;i++)cout << A[i] <<― ―;
cout << endl;
cout << ―The size of vector A is,― << A() << endl;
}
15:06:48
4.重载插入运算符与提取运算符,<< >>
对类 X重载插入运算符的一般形式为
friend ostream & operator<<(ostream &,const X&);
对类 X重载提取运算符的一般形式为
friend istream & operator>>(istream &,X &);
例:复数类对象的输入 /输出
//Complex.h
#include <iostream>
class Complex{
float real,image;
public:
…
friend std::ostream & operator<< (std::ostream &os,
const Complex & c);
friend std::istream & operator>> (std::istream &is,
Complex & c);
};
15:06:48
重载插入、提取运算符的实现
#include <iostream>
#include ―Complex.h‖
using namespace std;
ostream& operator<<(ostream& os,const Complex& c){
os << c.real << "+ (" << c.image << ")i";
return os;
}
istream& operator>> (istream& is,Complex& c){
is >> c.real >> c.image;
return is;
}
#include <iostream>
#include ―Complex.h‖
using namespace std;
void main(){
Complex c1,c2;
cin >> c1 >> c2;
cout << c1 <<endl << c2 << endl;
}
15:06:48
5.类型转换运算
(1).构造函数:隐式类型转换例,复数类完成以下运算时,调用构造函数进行了隐式类型转换
Complex left(3,4);
Complex result = left + 2.5f;
左操作数 left调用重载加法运算符对应的 operator+(… )函数,需要右操作数也为 Complex类型的对象,2.5f 不是
Complex类型的对象,需要进行类型转换
因为类中提供了构造函数
Complex (float r=0,float i=0);
所以这里先隐式调用该构造函数,把右操作数 2.5f 转换成一个实部为 2.5f,虚部为 0的临时复数对象,再调用
left.operator+(… )函数完成 left和临时复数对象的加法
15:06:48
例:要进行以下运算,除了调用构造函数进行隐式类型转换外,还需另外的代码
Complex right(3,4);
Complex result = 2.5f + right;
左操作数 2.5f不是 Complex类的对象,因此编译器不知该如何完成这样的 +操作,将会报告语法错误解决这样的问题,有两种方法:
方法一:提供 上述构造函数,并修改上述 +对应的重载函数
class Complex{
float real,image;
public:
Complex (float r=0,float i=0){real=r;image=i;}
Complex (const Complex & c);
friend Complex operator +(const Complex & left,
const Complex & right);
};
15:06:48
实现:
Complex operator+(const Complex& left,
const Complex& right)
{
Complex result;
result.real = left.real + right.real;
result.image = left.image + right.image;
return result;
}
Complex left(1,2),right(3,4);
Complex result1 = left + 2.5f;
Complex result2 = 2.5f + right;
这两处 + 都会调用重载后得到的友元函数都调用构造函数进行转换
15:06:48
方法二:提供 上述构造函数,不修改上述 +的重载函数,
再以另一种形式对 +进行重载
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
Complex operator +(const Complex& right);//已存在
friend Complex operator+(float fLeft,
const Complex & right);
};
15:06:48
实现
Complex Complex::operator+(const Complex & right){
Complex result;
result.real = real + right.real;
result.image = image + right.image;
return result;
}
Complex operator+(float fLeft,const Complex& right){
Complex result;
result.real = fLeft + right.real;
result.image = right.image;
return result;
}
Complex left(1,2),right(3,4);
Complex result1 = left + 2.5f;
Complex result2 = 2.5f + right;
调用构造函数进行类型转换不进行类型转换
15:06:48
(2).类型转换运算符的重载重载的一般形式为:
类名,:operator 目标类型 ();
例:用重载后的类型转换求复数的模
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
operator float();
};
Complex::operator float(){
return sqrt(real*real+image*image);
}
Complex c(1,2);
cout << float(c);
15:06:48
例:用重载后的类型转换将复数转换为 bool值
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
operator bool();
};
Complex::operator bool()
{ return real*real + image*image!=0; }
Complex c;
… //通过运算得到 c的实部和虚部
if( c ) { … }
15:06:48
6.重载 new与 delete
重载 new与 delete运算符的一般形式,
void * operator new(size_t sz){ … }
void * operator new[](size_t sz){ … }
void operator delete(void * ptr){ … }
void operator delete[](void * ptr){ … }
sz为所需申请内存的字节数,ptr中为所要释放对象的地址
使用 new运算符时创建对象时,系统先分配对象或变量所需的空间,然后再调用构造函数 ;使用 delete运算符销毁对象时,系统先调用析构函数,再释放对象或变量所占用的内存空间 ;
重载 new与 delete时可改变的行为只有对内存的分配与释放这一部分,构造函数与析构函数的调用是强制性的,亦即重载的 new与 delete运算符函数中没有显式的调用类的构造函数与析构函数,该类的构造函数与析构函数也会自动被调用
15:06:48
.new与 delete运算符重载的两种方式,
重载为全局函数
重载成类的成员函数例,GlobalNewAndDelete
重载为全局运算符函数时,会影响到所有的数据类型,亦即程序中再用到 new,delete运算符时,调用的是重载过的 new、
delete运算符函数,系统原来的 new与 delete运算符无法使用例,three_d
此时运算符 new与 delete只对这一特定类能起作用,也就是说,
只有用 new或 delete创建或释放这一特定类的对象时,重载的
new与 delete运算符函数才会被调用若用 new或 delete创建或销毁其它类的对象或普通变量时,仍使用系统提供的 new与 delete运算符
15:06:48
运算符重载的一般规则运 算 符 实 现 方 式所有的一元运算符 成员函数
= () [] -> ->* 必须为成员函数
+ - * / % <<(左移 ) >>(右移 ) & | ^ ~
+= -= /= *= ^= &= |= %= >>= <<=
&& || ! 等等成员函数所有其它可重载运算符 友元函数总体规则:
能重载成成员函数的运算符,不要重载成友元函数左操作数不是本类对象时,一般需重载成友元函数不能重载的运算符
sizeof,*(指针运算符),,?,
15:06:48
1,运算符重载的目的
2,运算符重载的两种形式:成员函数和友元函数
3,一元运算符的重载 —— 重点
4,二元运算符的重载 —— 重点
5,不允许重载的运算符
6,运算符重载的一般规则 —— 重点
15:06:48
– 数据类型总是与相关的运算相联系的
– 对类来说,一般情况下,调用类中提供的成员函数完成对该类的对象的操作,但对某些类来说,这种方式显得很不自然,不符合日常的思维习惯例:复数加法
class Complex{
float real,image;
public:
Complex(float r=0,float i=0);
Complex(const Complex & c);
Complex Add(const Complex & right);
};
void main(){
Complex left(1,2),right(3,4);
Complex result;
result=left.Add(right);
}
存在的问题:
复数在数学上有很规范的运算和运算符,但本类中 用成员函数而不是使用数学上的运算符 代表对复数进行的数学运算,
显得很不自然,不符合人的思维习惯改进:
对复数类提供重载的运算符
15:06:48
运算符重载通过在类中建立运算符函数 (operator function)实现声明运算符函数的一般形式为返回值类形 operator 运算符 (形参运算量列表 );
例:复数的加法
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
Complex operator +(const Complex & right);
};
void main(){
Complex left(1,2),right(3,4);
Complex result;
result = left + right;
}
15:06:48
关于运算符重载的说明
运算符重载的目的是 为了语法上的方便,使用户尽可能以符合日常思维或比较自然的方式编写程序
运算符重载的实质是改变运算符本来的含义,使对特定数据类型的数据进行这种运算时,调用该运算符对应的函数重载运算符时,该运算实现什么操作完全取决于类的设计者
(函数体由类的设计者实现 ),但一般 应参照该运算符本来的意义,否则会引起语法或使用上的混乱
运算符重载是针对 特定类的对象之间的运算 的,基本数据类型 (如 int,float等 )的变量之间进行的运算不能重载
运算符重载没有也不能改变该运算符的优先级与结合性
只能重载已存在的运算符,不能通过重载的方式创造新的运算符,也不能改变该运算符的操作数数目
运算符重载有两种形式,成元函数与友元函数
以下几个运算符不能被重载
sizeof,*(指针运算符 ),,?,
15:06:48
一元运算符的重载
一元运算本身需要一个操作数
可重载成成员函数,也可重载成友元函数
成员函数:形式上无参数,操作数即为 this指针指向的对象
友元函数:形式上带有一个参数,该参数即为操作数例:一元运算符的重载
//成员函数
class Integer{
int i;
public:
Integer(int ii=0);
void show();
Integer operator+();
Integer operator-();
};
//友元函数
class Byte{
int b;
public:
Byte(int bb=0);
void show();
friend Byte operator+(
const Byte & bt);
friend Byte operator-(
const Byte & bt);
};
15:06:48
实现
//成员函数
Integer::Integer(int ii)
{ i=ii;}
void Integer::show()
{ cout << i << endl;}
Integer Integer::operator+()
{return *this;}
Integer Integer::operator-(){
Integer temp(-i);
return temp;
}
//友元函数
Byte::Byte(int bb)
{ b=bb;}
void Byte::show()
{ cout << b << endl;}
Byte operator+(
const Byte & bt)
{return bt;}
Byte operator-(
const Byte & bt){
Byte temp(-bt.b);
return temp;
}
15:06:48
一元运算符重载的特例,++,--
++与 --有前置与后置 (即 先 ++,先 --和 后 ++,后 --)两种形式
为了区别这两种形式,重载时对应的函数形式有所不同例,Integer类
.成员函数:以 ++为例
class Integer{
int i;
public:
Integer operator++();
Integer operator++(int);
};
Integer Integer::operator ++(){
i++;
return *this;
}
Integer Integer::operator++(int)
{
Integer temp = *this;
i++;
return temp;
}
前置形式 后置形式
Integer intObj(10);
++intObj;
intObj++;
15:06:48
.友元函数
class Byte{
int b;
public:
friend Byte operator++(Byte & bt);
friend Byte operator++(Byte & bt,int);
};
Byte operator++(Byte & bt){
bt.b++;
return bt;
}
Byte operator++(Byte & bt,int){
Byte temp=bt;
bt.b++;
return temp;
}
Byte btObj(10);
++btObj;
btObj++;
前置形式后置形式
15:06:48
二元运算符的重载
二元运算本身需要两个操作数
有些二元运算符既可重载成成元函数,也可重载成友元函数
成员函数:形式上需要一个形参,此形参做为右操作数,
左操作数为 this指针指向的对象
友元函数:形式上需要两个形参,分别代表左操作数和右操作数
15:06:48
例:复数类
class Complex{
float real,image;
public:
Complex(float r=0,float i=0){real=r;image=i;}
Complex operator +(const Complex & right);
friend Complex operator -(const Complex & left,
const Complex & right);
};
Complex Complex::operator +(const Complex & right){
Complex temp(real+right.real,image+right.image);
return temp;
}
Complex operator-(const Complex& left,
const Complex& right){
Complex temp(left.real-right.real,
left.image-right.image);
return temp;
}
Complex c1(1,2),c2(3,4);
Complex c3 = c1 + c2;
Complex c4 = c1 – c2;
注意:
二元运算符重载对应的成员函数 由左操作数调用,意即
c1+c2? c1.operator+(c2)
15:06:48
二元运算符重载的特殊情况
1.重载赋值运算符,=
重载函数的原型为:
类名 & 类名,:operator=(const 类名 &);
例,Name类的重载赋值运算符
class Name{
char *pname;
int size;
public:
Name & operator=(const Name & nm){
size=nm.size;
if(nm.pname!=NULL){
pname=new char[size + 1];
strcpy(pname,nm.pname);
}
return *this;
}
};
Name nm1(―张三,),nm2(―李四,);
nm2 = nm1;
赋值运算符 必须 被重载成成员函数若类中未重载赋值运算符,该类的对象之间也可以互相赋值,但完成的是位对位 (或成员对成员 )的赋值,与浅拷贝的情况类似
15:06:48
2.重载下标运算符,[]
重载函数的原型为返回值类型名 & 类名,:opeator[](int);
3.重载函数调用运算符,()
重载函数的原型为返回值类型名 类名,:operator()(形参类型列表 );
class vector{
int *v;
int len;
public:
vector(int size=1);
vector(const vector& vct);
~ vector();
int & operator[](int i);
int operator()();
};
下标运算符和函数调用运算符 必须被重载成成员函数
15:06:48
vector类的实现
vector::vector(int size){
if(size<=0){cout << ―Error in Size‖;abort();}
v = new int [size];len = size;
}
vector::vector(const vector & vct){
len=vct.len;
if(vct.v!=NULL){
v = new int [len];
for(int i=0;i<len;i++)v[i]=vct.v[i];
}
}
vector::~ vector()
{if (v!=NULL){delete []v;len=0;}}
int & vector::operator[](int i)
{ return v[i]; }
int vector::operator()()
{ return len; }
void main(){
int k,i;
cin >> k;
vector A(k);
for(i=0;i<k;i++)A[i]=i+1;
for(i=0;i<k;i++)cout << A[i] <<― ―;
cout << endl;
cout << ―The size of vector A is,― << A() << endl;
}
15:06:48
4.重载插入运算符与提取运算符,<< >>
对类 X重载插入运算符的一般形式为
friend ostream & operator<<(ostream &,const X&);
对类 X重载提取运算符的一般形式为
friend istream & operator>>(istream &,X &);
例:复数类对象的输入 /输出
//Complex.h
#include <iostream>
class Complex{
float real,image;
public:
…
friend std::ostream & operator<< (std::ostream &os,
const Complex & c);
friend std::istream & operator>> (std::istream &is,
Complex & c);
};
15:06:48
重载插入、提取运算符的实现
#include <iostream>
#include ―Complex.h‖
using namespace std;
ostream& operator<<(ostream& os,const Complex& c){
os << c.real << "+ (" << c.image << ")i";
return os;
}
istream& operator>> (istream& is,Complex& c){
is >> c.real >> c.image;
return is;
}
#include <iostream>
#include ―Complex.h‖
using namespace std;
void main(){
Complex c1,c2;
cin >> c1 >> c2;
cout << c1 <<endl << c2 << endl;
}
15:06:48
5.类型转换运算
(1).构造函数:隐式类型转换例,复数类完成以下运算时,调用构造函数进行了隐式类型转换
Complex left(3,4);
Complex result = left + 2.5f;
左操作数 left调用重载加法运算符对应的 operator+(… )函数,需要右操作数也为 Complex类型的对象,2.5f 不是
Complex类型的对象,需要进行类型转换
因为类中提供了构造函数
Complex (float r=0,float i=0);
所以这里先隐式调用该构造函数,把右操作数 2.5f 转换成一个实部为 2.5f,虚部为 0的临时复数对象,再调用
left.operator+(… )函数完成 left和临时复数对象的加法
15:06:48
例:要进行以下运算,除了调用构造函数进行隐式类型转换外,还需另外的代码
Complex right(3,4);
Complex result = 2.5f + right;
左操作数 2.5f不是 Complex类的对象,因此编译器不知该如何完成这样的 +操作,将会报告语法错误解决这样的问题,有两种方法:
方法一:提供 上述构造函数,并修改上述 +对应的重载函数
class Complex{
float real,image;
public:
Complex (float r=0,float i=0){real=r;image=i;}
Complex (const Complex & c);
friend Complex operator +(const Complex & left,
const Complex & right);
};
15:06:48
实现:
Complex operator+(const Complex& left,
const Complex& right)
{
Complex result;
result.real = left.real + right.real;
result.image = left.image + right.image;
return result;
}
Complex left(1,2),right(3,4);
Complex result1 = left + 2.5f;
Complex result2 = 2.5f + right;
这两处 + 都会调用重载后得到的友元函数都调用构造函数进行转换
15:06:48
方法二:提供 上述构造函数,不修改上述 +的重载函数,
再以另一种形式对 +进行重载
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
Complex operator +(const Complex& right);//已存在
friend Complex operator+(float fLeft,
const Complex & right);
};
15:06:48
实现
Complex Complex::operator+(const Complex & right){
Complex result;
result.real = real + right.real;
result.image = image + right.image;
return result;
}
Complex operator+(float fLeft,const Complex& right){
Complex result;
result.real = fLeft + right.real;
result.image = right.image;
return result;
}
Complex left(1,2),right(3,4);
Complex result1 = left + 2.5f;
Complex result2 = 2.5f + right;
调用构造函数进行类型转换不进行类型转换
15:06:48
(2).类型转换运算符的重载重载的一般形式为:
类名,:operator 目标类型 ();
例:用重载后的类型转换求复数的模
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
operator float();
};
Complex::operator float(){
return sqrt(real*real+image*image);
}
Complex c(1,2);
cout << float(c);
15:06:48
例:用重载后的类型转换将复数转换为 bool值
class Complex{
float real,image;
public:
Complex (float r=0,float i=0);
Complex (const Complex & c);
operator bool();
};
Complex::operator bool()
{ return real*real + image*image!=0; }
Complex c;
… //通过运算得到 c的实部和虚部
if( c ) { … }
15:06:48
6.重载 new与 delete
重载 new与 delete运算符的一般形式,
void * operator new(size_t sz){ … }
void * operator new[](size_t sz){ … }
void operator delete(void * ptr){ … }
void operator delete[](void * ptr){ … }
sz为所需申请内存的字节数,ptr中为所要释放对象的地址
使用 new运算符时创建对象时,系统先分配对象或变量所需的空间,然后再调用构造函数 ;使用 delete运算符销毁对象时,系统先调用析构函数,再释放对象或变量所占用的内存空间 ;
重载 new与 delete时可改变的行为只有对内存的分配与释放这一部分,构造函数与析构函数的调用是强制性的,亦即重载的 new与 delete运算符函数中没有显式的调用类的构造函数与析构函数,该类的构造函数与析构函数也会自动被调用
15:06:48
.new与 delete运算符重载的两种方式,
重载为全局函数
重载成类的成员函数例,GlobalNewAndDelete
重载为全局运算符函数时,会影响到所有的数据类型,亦即程序中再用到 new,delete运算符时,调用的是重载过的 new、
delete运算符函数,系统原来的 new与 delete运算符无法使用例,three_d
此时运算符 new与 delete只对这一特定类能起作用,也就是说,
只有用 new或 delete创建或释放这一特定类的对象时,重载的
new与 delete运算符函数才会被调用若用 new或 delete创建或销毁其它类的对象或普通变量时,仍使用系统提供的 new与 delete运算符
15:06:48
运算符重载的一般规则运 算 符 实 现 方 式所有的一元运算符 成员函数
= () [] -> ->* 必须为成员函数
+ - * / % <<(左移 ) >>(右移 ) & | ^ ~
+= -= /= *= ^= &= |= %= >>= <<=
&& || ! 等等成员函数所有其它可重载运算符 友元函数总体规则:
能重载成成员函数的运算符,不要重载成友元函数左操作数不是本类对象时,一般需重载成友元函数不能重载的运算符
sizeof,*(指针运算符),,?,
15:06:48