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表明调用函数对象不会被修改!
想必看到这里对重载运算符算是有一丁点的了解吧,下面看些理论文字,更加清楚的了解关系!
重载运算符的介绍
运算符重载时要遵循以下规则:
成员函数运算符
当运算符重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置单目运算符除外),这是因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。因此:
友元函数运算符
当运算符重载为类的友元函数时,由于没有隐含的this指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的形参进行传递,函数的参数与操作数自左至右一一对应。
两种重载形式的比较
在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。但成员函数运算符与友元函数运算符也具有各自的一些特点:
下面具体讲讲重载运算符的一些具体用法吧!
1.一般运算符重载
在进行对象之间的运算时,程序会调用与运算符相对应的函数进行处理,所以运算符重载有两种方式:成员函数和友元函数。成员函数的形式比较简单,就是在类里面定义了一个与操作符相关的函数。友元函数因为没有this指针,所以形参会多一个。
1 class A 2 { 3 public: 4 A(int d):data(d){} 5 A operator+(A&);//成员函数 6 A operator-(A&); 7 A operator*(A&); 8 A operator/(A&); 9 A operator%(A&); 10 friend A operator+(A&,A&);//友元函数 11 friend A operator-(A&,A&); 12 friend A operator*(A&,A&); 13 friend A operator/(A&,A&); 14 friend A operator%(A&,A&); 15 private: 16 int data; 17 }; 18 //成员函数的形式 19 A A::operator+(A &a) 20 { 21 return A(data+a.data); 22 } 23 A A::operator-(A &a) 24 { 25 return A(data-a.data); 26 } 27 A A::operator*(A &a) 28 { 29 return A(data*a.data); 30 } 31 A A::operator/(A &a) 32 { 33 return A(data/a.data); 34 } 35 A A::operator%(A &a) 36 { 37 return A(data%a.data); 38 } 39 //友元函数的形式 40 A operator+(A &a1,A &a2) 41 { 42 return A(a1.data+a2.data); 43 } 44 A operator-(A &a1,A &a2) 45 { 46 return A(a1.data-a2.data); 47 } 48 A operator*(A &a1,A &a2) 49 { 50 return A(a1.data*a2.data); 51 } 52 A operator/(A &a1,A &a2) 53 { 54 return A(a1.data/a2.data); 55 } 56 A operator%(A &a1,A &a2) 57 { 58 return A(a1.data%a2.data); 59 } 60 //然后我们就可以对类的对象进行+、-、*、/了。 61 void main(void) 62 { 63 A a1(1),a2(2),a3(3); 64 a1=a2+a3; 65 //或者 66 a1=a2.operator+(a3); 67 }
注意:在进行a2+a3的时候会出错,因为我们在上面对+定义了两种方法,去掉一种即可。
2.关系运算符重载
因为函数体比较简单,后面我就只给出成员函数形式的函数声明了,关系运算符有==,!=,<,>,<=,>=。
1 bool operator == (const A& ); 2 bool operator != (const A& ); 3 bool operator < (const A& ); 4 bool operator <= (const A& ); 5 bool operator > (const A& ); 6 bool operator >= (const A& );
3.逻辑运算符重载
1 bool operator || (const A& ); 2 bool operator && (const A& ); 3 bool operator ! ();
4.单目运算符重载
这里的+、-是正负的意思,放在对象前面。
1 A& operator + (); 2 A& operator - (); 3 A* operator & (); 4 A& operator * ();
5.自增减运算符重载
++和–根据位置的不同有四种情况,都可以重载。
1 A& operator ++ ();//前置++ 2 A operator ++ (int);//后置++ 3 A& operator --();//前置-- 4 A operator -- (int);//后置--
6.位运算符重载
按位操作。
1 A operator | (const A& ); 2 A operator & (const A& ); 3 A operator ^ (const A& ); 4 A operator << (int i); 5 A operator >> (int i); 6 A operator ~ ();
7.赋值运算符重载
没有=哦。
1 A& operator += (const A& ); 2 A& operator -= (const A& ); 3 A& operator *= (const A& ); 4 A& operator /= (const A& ); 5 A& operator %= (const A& ); 6 A& operator &= (const A& ); 7 A& operator |= (const A& ); 8 A& operator ^= (const A& ); 9 A& operator <<= (int i); 10 A& operator >>= (int i);
8.内存运算符重载
1 void *operator new(size_t size); 2 void *operator new(size_t size, int i); 3 void *operator new[](size_t size); 4 void operator delete(void*p); 5 void operator delete(void*p, int i, int j); 6 void operator delete [](void* p);
9.特殊运算符重载
上面的运算符重载都有两种方式,而下面的运算符只能用一种,特殊吧。 这些运算符的重载只能是成员函数。
1 A& operator = (const A& ); 2 char operator [] (int i);//返回值不能作为左值 3 const char* operator () (); 4 T operator -> (); 5 //类型转换符 6 operator char* () const; 7 operator int (); 8 operator const char () const; 9 operator short int () const; 10 operator long long () const; 11 //还有很多就不写了
而这些只能以友元函数的形式重载
1 friend inline ostream &operator << (ostream&, A&);//输出流 2 friend inline istream &operator >> (istream&, A&);//输入流
10.总结
两种重载方式的比较:
- 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
- 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
- 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。 C++提供4个类型转换函数:reinterpret_cast(在编译期间实现转换)、const_cast(在编译期间实现转换)、stactic_cast(在编译期间实现转换)、dynamic_cast(在运行期间实现转换,并可以返回转换成功与否的标志)。
- 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
- 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
- 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部 类型的对象,该运算符函数必须作为一个友元函数来实现。
- 当需要重载运算符具有可交换性时,选择重载为友元函数。
注意事项:
- 除了类属关系运算符”.“、成员指针运算符”.*“、作用域运算符”::“、sizeof运算符和三目运算符”?:“以外,C++中的所有运算符都可以重载。
- 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
- 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
- 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
- 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
- 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。
作 者:Angel_Kitty
出 处:https://www.cnblogs.com/ECJTUACM-873284962/
关于作者:阿里云ACE,目前主要研究方向是Web安全漏洞以及反序列化。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
欢迎大家关注我的微信公众号IT老实人(IThonest),如果您觉得文章对您有很大的帮助,您可以考虑赏博主一杯咖啡以资鼓励,您的肯定将是我最大的动力。thx.
我的公众号是IT老实人(IThonest),一个有故事的公众号,欢迎大家来这里讨论,共同进步,不断学习才能不断进步。扫下面的二维码或者收藏下面的二维码关注吧(长按下面的二维码图片、并选择识别图中的二维码),个人QQ和微信的二维码也已给出,扫描下面👇的二维码一起来讨论吧!!!
欢迎大家关注我的Github,一些文章的备份和平常做的一些项目会存放在这里。