C/C++对bool operator < (const p &a)const的认识,运算符重载详解(杂谈)
下面来进行这段代码的分析:
struct
node {
//定义一个结构体node(节点)
int
x;
int
y;
int
len;
//node中有3个成员变量x,y,len
bool
operator <(
const
node &a)
const
{
//重载<操作符。可以对两个node使用<操作符进行比较
return
len<a.len;
}
};
括号中的const表示参数a对象不会被修改,最后的const表明调用函数对象不会被修改!
想必看到这里对重载运算符算是有一丁点的了解吧,下面看些理论文字,更加清楚的了解关系!
重载运算符的介绍
运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进行的操作。运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。运算符函数定义的一般格式如下:
运算符重载时要遵循以下规则:
运算符函数重载一般有两种形式:重载为类的成员函数和重载为类的非成员函数。非成员函数通常是友元。(可以把一个运算符作为一个非成员、非友元函数重载。但是,这样的运算符函数访问类的私有和保护成员时,必须使用类的公有接口中提供的设置数据和读取数据的函数,调用这些函数时会降低性能。可以内联这些函数以提高性能。)
成员函数运算符
当运算符重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置单目运算符除外),这是因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。因此:
友元函数运算符
当运算符重载为类的友元函数时,由于没有隐含的this指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的形参进行传递,函数的参数与操作数自左至右一一对应。
两种重载形式的比较
在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。但成员函数运算符与友元函数运算符也具有各自的一些特点:
下面具体讲讲重载运算符的一些具体用法吧!
1.一般运算符重载
在进行对象之间的运算时,程序会调用与运算符相对应的函数进行处理,所以运算符重载有两种方式:成员函数和友元函数。成员函数的形式比较简单,就是在类里面定义了一个与操作符相关的函数。友元函数因为没有this指针,所以形参会多一个。
class A
{
public:
A(int d):data(d){}
A operator+(A&);//成员函数
A operator-(A&);
A operator*(A&);
A operator/(A&);
A operator%(A&);
friend A operator+(A&,A&);//友元函数
friend A operator-(A&,A&);
friend A operator*(A&,A&);
friend A operator/(A&,A&);
friend A operator%(A&,A&);
private:
int data;
};
//成员函数的形式
A A::operator+(A &a)
{
return A(data+a.data);
}
A A::operator-(A &a)
{
return A(data-a.data);
}
A A::operator*(A &a)
{
return A(data*a.data);
}
A A::operator/(A &a)
{
return A(data/a.data);
}
A A::operator%(A &a)
{
return A(data%a.data);
}
//友元函数的形式
A operator+(A &a1,A &a2)
{
return A(a1.data+a2.data);
}
A operator-(A &a1,A &a2)
{
return A(a1.data-a2.data);
}
A operator*(A &a1,A &a2)
{
return A(a1.data*a2.data);
}
A operator/(A &a1,A &a2)
{
return A(a1.data/a2.data);
}
A operator%(A &a1,A &a2)
{
return A(a1.data%a2.data);
}
//然后我们就可以对类的对象进行+、-、*、/了。
void main(void)
{
A a1(),a2(),a3();
a1=a2+a3;
//或者
a1=a2.operator+(a3);
}
注意:在进行a2+a3的时候会出错,因为我们在上面对+定义了两种方法,去掉一种即可。
2.关系运算符重载
因为函数体比较简单,后面我就只给出成员函数形式的函数声明了,关系运算符有==,!=,<,>,<=,>=。
bool operator == (const A& );
bool operator != (const A& );
bool operator < (const A& );
bool operator <= (const A& );
bool operator > (const A& );
bool operator >= (const A& );
3.逻辑运算符重载
bool operator || (const A& );
bool operator && (const A& );
bool operator ! ();
4.单目运算符重载
这里的+、-是正负的意思,放在对象前面。
A& operator + ();
A& operator - ();
A* operator & ();
A& operator * ();
5.自增减运算符重载
++和–根据位置的不同有四种情况,都可以重载。
A& operator ++ ();//前置++
A operator ++ (int);//后置++
A& operator --();//前置--
A operator -- (int);//后置--
6.位运算符重载
按位操作。
A operator | (const A& );
A operator & (const A& );
A operator ^ (const A& );
A operator << (int i);
A operator >> (int i);
A operator ~ ();
7.赋值运算符重载
没有=哦。
A& operator += (const A& );
A& operator -= (const A& );
A& operator *= (const A& );
A& operator /= (const A& );
A& operator %= (const A& );
A& operator &= (const A& );
A& operator |= (const A& );
A& operator ^= (const A& );
A& operator <<= (int i);
A& operator >>= (int i);
8.内存运算符重载
void *operator new(size_t size);
void *operator new(size_t size, int i);
void *operator new[](size_t size);
void operator delete(void*p);
void operator delete(void*p, int i, int j);
void operator delete [](void* p);
9.特殊运算符重载
上面的运算符重载都有两种方式,而下面的运算符只能用一种,特殊吧。 这些运算符的重载只能是成员函数。
A& operator = (const A& );
char operator [] (int i);//返回值不能作为左值
const char* operator () ();
T operator -> ();
//类型转换符
operator char* () const;
operator int ();
operator const char () const;
operator short int () const;
operator long long () const;
//还有很多就不写了
而这些只能以友元函数的形式重载
friend inline ostream &operator << (ostream&, A&);//输出流
friend inline istream &operator >> (istream&, A&);//输入流
10.总结
两种重载方式的比较:
- 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
- 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
- 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。 C++提供4个类型转换函数:reinterpret_cast(在编译期间实现转换)、const_cast(在编译期间实现转换)、stactic_cast(在编译期间实现转换)、dynamic_cast(在运行期间实现转换,并可以返回转换成功与否的标志)。
- 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
- 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
- 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部 类型的对象,该运算符函数必须作为一个友元函数来实现。
- 当需要重载运算符具有可交换性时,选择重载为友元函数。
注意事项:
- 除了类属关系运算符”.“、成员指针运算符”.*“、作用域运算符”::“、sizeof运算符和三目运算符”?:“以外,C++中的所有运算符都可以重载。
- 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
- 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
- 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
- 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
- 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。
C/C++对bool operator < (const p &a)const的认识,运算符重载详解(杂谈)的更多相关文章
- 类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete
一.类型转换运算符 必须是成员函数,不能是友元函数 没有参数 不能指定返回类型 函数原型:operator 类型名(); C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 1 ...
- [STL]set/multiset用法详解[自从VS2010开始,set的iterator类型自动就是const的引用类型]
集合 使用set或multiset之前,必须加入头文件<set> Set.multiset都是集合类,差别在与set中不允许有重复元素,multiset中允许有重复元素. sets和mul ...
- C2678 二进制“<”: 没有找到接受“const ***”类型的左操作数的运算符解决办法
正确代码如下:#include<iostream> #include<string> #include<map> using namespace std; /*仿函 ...
- (转) C/C++中const关键字详解
文章转自 http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 为什么使用const?采用符号常量写出的代码更容易维 ...
- C++初学者 const使用详解
关于C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,参考了康建东兄的const使用详解一文,对其中进行了一些补充,写下了本文. 1. const常量 如: cons ...
- C++ 中的 const 详解
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4235721.html 1.为什么使用 const int 而不使用 #define 在使用# ...
- 【转】C++ 内存分配(new,operator new)详解
本文主要讲述C++ new运算符和operator new, placement new之间的种种关联,new的底层实现,以及operator new的重载和一些在内存池,STL中的应用. 一 new ...
- [置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)
operator overloading(操作符重载,运算符重载) 所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型).操作符重 ...
- c++ 学习之const专题之const成员函数
一些成员函数改变对象,一些成员函数不改变对象. 例如: int Point::GetY() { return yVal; } 这个函数被调用时,不改变Point对象,而下面的函数改变Point对象: ...
随机推荐
- Java Stream API入门篇
本文github地址 你可能还没意识到Java对函数式编程的重视程度,看看Java 8加入函数式编程扩充多少类就清楚了.Java 8之所以费这么大功夫引入函数式编程,原因有二: 代码简洁,函数式编程写 ...
- 3856: Monster
3856: Monster Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 351 Solved: 161[Submit][Status][Discuss ...
- 【NFS项目实战二】NFS共享数据的时时同步推送备份
[NFS项目实战二]NFS共享数据的时时同步推送备份 标签(空格分隔): Linux服务搭建-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品, ...
- 【转】nginx配置:location配置方法及实例详解
location匹配的是nginx的哪个变量? $request_uri location的匹配种类有哪些? 格式 location [ 空格 | = | ~ | ~* | !~ | !~* ] /u ...
- js 判断是否为空对象、空数组
当需要判断参数是否为空时,总希望 js 能够提供原生的判断方法,可惜并没有,只能自己封装了. function isEmpty(obj) { // 检验 undefined 和 null if(!ob ...
- 【翻译】CSS水平和垂直居中的12种方法
英语原文链接 在CSS中有许多不同的方法能够做到水平和垂直居中,但很难去选择合适的那个.我会向你展示我所看到的所有的方法,帮助你在所面对的情境下选择最棒的那一个. 方法1 此方法将只能垂直居中单行文本 ...
- Python 使用心得之--变量命名
目前开发命名规范基本都遵循驼峰命名法,如:userName.我也不将这个规范的特性了,大家都明白.接下来进入正题,如何在python中取一个好名字,让你能更好的见名知意呢? 1.元组(Tuple)类型 ...
- HTTP认证
参考博文:HTTP协议详解 HTTP请求报头: Authorization HTTP响应报头: WWW-Authenticate HTTP认证是基于质询/回应(challenge/response)的 ...
- cent os 直接访问谷歌的脚本实现
https://github.com/DingGuodong/GoogleHostsFileForLinux/blob/master/replaceLocalHostsFileAgainstGfw.s ...
- Java并发编程:线程控制
在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...