C++重载运算符的分析
发布日期:2021-05-07 01:18:11 浏览次数:22 分类:原创文章

本文共 2826 字,大约阅读时间需要 9 分钟。

C++重载运算符的分析

一、重载运算符

重载运算符,顾名思意,其实就是把一种运算符重新定义成另外一种含义。举一个简单的例子,大家熟知的+这个运算符,应用在数学上,很好理解,但是如果有一个动物类,这个动物类的两从此实例对象相加,是什么意思呢?这就是重载的目的。比如这个动物类中有重量,在动物类中重载这个+运算符,两个实例对象相加就代表着重量的相加,当然,也可以定义成其它,比如每天吃的粮食的重量。
从这个意义上来说,重载运算符给了c++以很大的灵活性,所以做为c++的一项基础的功能,要把它掌握好。

二、重载运算符的种类

1、c++可以重载的运算符

      • / % ^ & | ~ ! = > < += -= = /= %= ^= &=
        |= >> << >>= <<= == != >= <= && || ++ – ->
        , -> [] () new new[]
        delete delete []
        上面这些运算是都可以重载的。一些细节会在后面展开。

2、c++不可以重载的运算符

:: . .* ? : sizeof typeid new delete
static_cast dynamic_cast const_cast reinterpret_cast

3、用户可自定义运算符

这个就比较灵活了,比如:

float operator ""_e(const char*);

3、重载使用的形式

重载运算符可以使用两种形式进行,一种是在类内操作,即重载运算符的函数属于类本身;另外一种是使用友元函数来操作,使用友元的方便之处在于可以访问类的私有变量,恰好有些运算符需要操作类自身的私有属性。

4、使用的一般原则

1、重载一元操作符既可以是成员函数也可以是非成员函数,一元操作符在成员函数无参,否则有一个参数。
2、重载二元操作符同上,但参数相应增加一个。
3、重载=、[]、()、->只能定义为成员函数(这是规定,不要问为什么)。
4、重载->的返回值必须是一个指针或能使用->的对象。
5、重载 ++ 和 – 时带一个 int 参数表示后缀,不带参数表示前缀(区分a++,++a)。
6、除 new 和delete 外,重载的操作符参数中至少要有一个非内部数据类型(非c++自已定义的类型)。
7、x@y决定顺序:x 成员函数;全局函数;X所在名字空间中的函数;Y所在名字空间中的函数;X的友元函数;Y的友元函数。
8、重载的运算符尽量和c++的意义保持一致或者符合正常的思维。
以上这些在c++标准的文档中第十三章中有相关的说明。

5、一些实践的经验

1、一元操作符尽量重载为成员函数。
2、<<和>>两个操作符为和标准库保持一致,尽量重载为非成员函数
3、重载[]这些运算符,应该提供const和非const两个版本。
4、重载不要引起歧义或者多义。
5、不是必须,尽量不要重载new ,delete相关运算符。

三、例子分析

下面分析一个简单的例子,重载了<<运算符:

#include <iostream>using namespace std;class Person {public:	Person(int age, int score);  //既可以重载为友元,也可以重载为内部成员函数  //不过如果使用ostream的话,就只能使用友元,因为标准库不能修改	friend ostream&operator <<(ostream &os,Person&p);	// Person&operator <<(int d);public:  //公有的目的是为了验证结果  int m_age;	int m_score;};Person::Person(int age, int score){	this->m_age = age;	this->m_score = score;}ostream&operator <<(ostream &os, Person&p ){	os << "age  " << p.m_age << " score " << p.m_score;	return os;}//注释的是处理自己对<<的重载,意思是重载为成员函数也是可以的//Person&Person::operator <<(int os)//{//	//os << "age  " << p.m_age << " score " << p.m_score;//	this->m_age = this->m_score = os;//	return *this;//}int main(){	Person p(1, 100);	//std:cout << p << std::endl;	//Person b = Person(2, 1);	std:cout << p << std::endl;	//p << 100;	//std::cout << p.m_age << p.m_score << std::endl;    return 0;}

这里使用了两种形式,既有成员函数也有友元函数,注释里写得也比较清楚,这里再次说明一下,如果想把自己的类与ostream相兼容,互通使用<<或者>>运算符,就只能使用友元函数,否则直接修改标准库的重载,太不划算了。
标准库自带的前后缀示例:

struct X {X& operator++(); // prefix ++aX operator++(int); // postfix a++};struct Y { };Y& operator++(Y&); // prefix ++bY operator++(Y&, int); // postfix b++void f(X a, Y b) {++a; // a.operator++();a++; // a.operator++(0);++b; // operator++(b);b++; // operator++(b, 0);a.operator++(); // explicit call: like ++a;a.operator++(0); // explicit call: like a++;operator++(b); // explicit call: like ++b;operator++(b, 0); // explicit call: like b++;}

如果还是有什么疑问,可以下载c++的标准文档,仔细研究。

四、总结

其实上面的总结还是有些流于形式,只有深入的学习标准文档并加以实践,才能真正的把重载用好。c++的灵活性在这里体现的也比较明显,除了个别强制要求,其它都可以灵活的选择你的重载方式。即使重载的方式反人类的认知方式,c++的编译器也不会认为是错误的。
经验,既是优势,也是累赘。经验需要不断的总结提取否定进步。

上一篇:P和NP及NPC的问题
下一篇:线性代数之基本向量

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2025年04月13日 07时38分57秒