C++运算符重载——重载特殊运算符
1、重载赋值运算符=
赋值运算符用于同类对象间的相互赋值。赋值运算符只能被重载为类的非静态成员函数,不能重载为友元函数和普通函数。
对于用户自定义的类而言,如果没有重载赋值运算符,那么C++编译器会为该类提供一个默认的重载赋值运算符成员函数。
默认赋值运算符的工作方式是按位对拷,将等到右边对象的非静态成员拷贝给等号左边的对象。
重载赋值运算符函数必须是public的,否则会编译错误,因为用户定义了重载赋值运算符函数,编译器就不会提供默认的。
在类中重载的赋值运算符函数不能被继承!
通常情况下编译器提供的默认重载赋值运算符函数能够解决对象间赋值的问题,但是当类中含有指针数据成员时,容易引起指针悬挂的问题,
所以这种情况下有必要进行赋值运算符重载。
举一个例子,下面的程序使用默认的重载赋值运算符函数,在Linux下运行会检测到double free的问题,其实还有一个内存泄漏的问题(使用valgrind工具检测),即指针悬挂。
原因是对象之间赋值时,对象s2的指针成员pstr的值被赋值成对象s1的指针成员pstr的值,这时对象s2中申请的堆空间就被遗忘了,程序结束时没有人释放,
同时s2对象析构时,释放的是所s1申请的堆空间,s1对象析构时,就产生了2次释放的问题。
#include <cstring>
#include <iostream>
using namespace std; class MyString
{
public:
MyString(const char* str){count = strlen(str);pstr = new char[count+];strcpy(pstr, str);}
~MyString(){delete []pstr;}
void display(void){cout<<pstr<<endl;}
private:
char *pstr;
int count;
};
int main(void)
{
MyString s1("Hello");s1.display();
MyString s2("World");s2.display(); s2 = s1;s2.display();//glibc detected : double free or corruption return ;
} /** valgrind 结果
Invalid free() / delete / delete[] / realloc()
LEAK SUMMARY:
definitely lost: 6 bytes in 1 blocks
**/
下面使用自定义赋值运算符重载来解决内存泄漏和2次释放的问题。
#include <cstring>
#include <iostream>
using namespace std; class MyString
{
public:
MyString(const char* str){count = strlen(str);pstr = new char[count+];strcpy(pstr, str);}
~MyString(){delete []pstr;}
void display(void){cout<<count<<":"<<pstr<<endl;}
//operator overload : =
MyString& operator=(MyString& ref)
{
if (this != &ref)
{
delete []pstr;
count = ref.count;
pstr = new char[count+];
strcpy(pstr, ref.pstr);
}
return (*this);
} private:
char *pstr;
int count;
};
int main(void)
{
MyString s1("Hello");s1.display();
MyString s2("World");s2.display(); s2 = s1;s2.display();//OK return ;
}
2、重载下标运算符[]
下标运算符只能被重载为类的非静态成员函数,不能重载为友元函数和普通函数。
由于[]既可以作为左值又可以作为右值,所以重载下标运算符函数通常返回引用。
于其他运算符重载有一点不同的是:[]重载的功能是多样的,完全取决于用户的定义,但是通常是数组相关的。
重载的下标运算符函数只能有一个参数,即使用的方式只能是 Aclss[para],不能没有参数或者是Aclss[para1, para2]多参数的形式。
例子:通过重载下标运算符,可以很方便的取得和修改类中的数组。
#include <iostream>
using namespace std; class MyArrary
{
public:
MyArrary(int a1,int a2,int a3, int a4){arr[]=a1;arr[]=a2;arr[]=a3;arr[]=a4;} //operator overload : []
int& operator[](int num)//返回引用才能进行赋值操作
{
if ((num < ) || (num > ))
{
cout <<"error:";
num = ;
}
return arr[num];
} private:
int arr[];
}; int main(void)
{
MyArrary ma(,,,);
cout << ma[]<<endl; //取值
ma[] = ; //赋值
cout << ma[]<<endl;
return ;
}
3、重载括号运算符()
括号运算符只能被重载为类的非静态成员函数,不能重载为友元函数和普通函数。
由于()既可以作为左值又可以作为右值,所以重载括号运算符函数通常返回引用。
重载括号运算符函数的参数个数没有限制,甚至没有参数都可以。
例子:通过重载括号运算符,可以很方便的取得和修改类中的数组。
#include <iostream>
using namespace std; class DArrary
{
public:
DArrary(int num){int i = ; for (i = ; i< ;i++) arr[i/][i%] = num++;}
void display(void){int i = ;for (i = ; i< ;i++) cout<<arr[i/][i%]<<" ";cout<<endl;} //operator overload : () Multiple Parameters
int& operator()(int a, int b)
{
return arr[a][b];
} //operator overload : () Singal Parameter
int& operator()(int a)
{
return arr[a/][a%];
}
//operator overload : () None Parameter
int& operator()(void)
{
return arr[][];
}
private:
int arr[][];
};
int main(void)
{
DArrary arr();arr.display();
cout << arr(,) << endl; //取值
cout << arr(,) << endl; //取值
arr(,) = ; //赋值
arr(,) = ; //赋值
cout << arr(,) << endl;
cout << arr(,) << endl; cout << arr() << endl; //取值
arr() = ; //赋值
cout << arr() << endl; cout << arr() << endl;
arr() = ;
arr.display();
return ;
}
C++运算符重载——重载特殊运算符的更多相关文章
- C++ Primer : : 第十四章 : 重载运算符与类型转换之类型转换运算符和重载匹配
类型转换运算符 class SmallInt { public: SmallInt(int i = 0) : val(i) { if (i < 0 || i > 255) throw st ...
- C++运算符重载——重载二元运算符
1.重载二元操作符的方法 二元运算符又称为双目运算符,即需要2个操作数的运算符,例如 + - * / 等. 运算符重载可以分为3种方式:类的非静态成员函数.类的友元函数.普通函数. 例如有 2 个操作 ...
- C++运算符重载——重载一元运算符
0.重载一元操作符的方法 一元运算符即只需要一个操作用的运算符,如取地址运算符(&).复数(-).自减(--).自加(++)等. 运算符重载可以分为3种方式:类的非静态成员函数.类的友元函数. ...
- C++重载流插入运算符和流提取运算符【转】
C++的流插入运算符“<<”和流提取运算符“>>”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream.cin和cout分别是 ...
- [置顶] C++基础之六:运算符的重载
网上太多有关运算符的重载了,但是写的太过的详细,不适合新手入门,特别是那什么++和--的前增量后增量重载,一元二元运算符重载,特殊运算符,下标运算符,new和delete,甚至是指针运算符的重载,吓退 ...
- C++运算符重载——输入/输出运算符
为了与IO标准库一致,重载输入输出运算符函数的第一个行参应该是流的引用,第二个行参是对象的引用. 如果重载为类的成员函数,第一个行参应该是对象的引用,第二个行参是流的引用. 使用方式是 ClassOb ...
- 【转】C++对成员访问运算符->的重载
运算符->的重载比较特别,它只能是非静态的成员函数形式,而且没有参数. 1.如果返回值是一个原始指针,那么就将运算符的右操作数当作这个原始指针所指向类型的成员进行访问: 2.如果返回值是另一个类 ...
- C++ 重载运算符和重载函数
C++ 重载运算符和重载函数 C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是 ...
- C++解析七-重载运算符和重载函数
重载运算符和重载函数C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载.重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列 ...
随机推荐
- P1689: [Usaco2005 Open] Muddy roads 泥泞的路
水题,模拟就行了,别忘了L>=r的时候直接更新下一个的L然后continue type node=record l,r:longint; end; var n,l,i,ans:longint; ...
- Week8 软件规格说明书
1.概述 本项目组所开发的软件为一个基于Android的手机端的时间管理软件,主要功能为时间管理软件,可以用于管理待办事项,记录一些需要提醒的信息等.有事件提醒.与Google账户同步.课程表等功能. ...
- Scrum仪式之Sprint计划会议
会议时间:4.15.晚八点 会议地点:基础教学楼二楼 会议进程 • 首先我们讨论了实验第一个Sprint1要实现的功能,我们的初期目标.• 然后我们进一步梳理了第一阶段的任务和需求.• 之后对任务 ...
- C语言编写的随机产生四则运算测试题
题目:编写一个四则运算测试题的程序,要求每道题都要随机产生 解题思路: 1.编写测试题,且为30道,就要用到循环函数,因此想到用for()函数 2.随机产生两个数,就想到用rand()函数. 注:1. ...
- 关于myeclipse代码提示的一些问题
默认是 .xxx 输入点提示,要写注释 @xxx的时候怎么输入@后面有代码提示呢? Auto activation delay 是代码提示出现的速度 下面一行是出现代码提示的条件 我们在.后面加 ...
- eclipse编辑jsp文件和javascript代码很卡解决办法
1.Window -> Preference -> General -> Editors -> Text Editors -> HyperLinking -> 在用 ...
- 【BZOJ】【2756】【SCOI2012】奇怪的游戏
网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.co ...
- vs2008 添加与修改模板.
添加 我的模板: 路径: C:\Users\Administrator\Documents\Visual Studio 2008\Templates\ItemTemplates\Visual C# ...
- AngularJs学习笔记--expression
原版地址:http://code.angularjs.org/1.0.2/docs/guide/expression 表达式(Expressions)是类Javascript的代码片段,通常放置在绑定 ...
- js实用功能
//日期格式转换 Date.prototype.format = function (format) { /* * eg:format="yyyy-MM-dd hh:mm: ...