合肥建设学校网站,界面做的比较好的网站,wordpress 速度优化,陕西省建设资格注册中心网站支持重载操作符是c的一个特性#xff0c;先不管好不好用#xff0c;这起码能让它看起来比其他语言NB很多#xff0c;但真正了解重载操作符后#xff0c;就会发现这个特性...就这#xff1f;本文分两个部分
重载操作符简介和使用——适用新手重载操作符的原理和sao操作——…支持重载操作符是c的一个特性先不管好不好用这起码能让它看起来比其他语言NB很多但真正了解重载操作符后就会发现这个特性...就这本文分两个部分
重载操作符简介和使用——适用新手重载操作符的原理和sao操作——适用装杯选手
1 简介 使用
c支持重载的操作符有 算术操作符 、-、*、/、% 关系操作符 、!、、、、 逻辑操作符 !、、|| 位操作符 ~、、|、^、、 赋值操作符 、、-、*、/、%、、|、^、、 下标操作符 [] 函数调用操作符 () 成员访问操作符 - 指针操作符 *(解引用)、(取地址) 逗号操作符 ,
这些操作符按照操作数个数不同分为单目操作符、双目操作符、多目操作符 单目操作符 !、~、-、*(解引用)、(取地址) 双目操作符 其他 多目操作符 ()
为什么要按这个分类别急继续看...
用法
重载操作符实际上就是重新定义操作符的行为函数不过这里需要用到一个关键字operator。大多数操作符有两种重载方式
类成员函数重载全局函数重载
例如
// 成员函数重载Point类的操作符和~操作符 —— 定义在类内部
struct Point {Point operator(const Point oth) const { ... }Point operator~() const { ... }
};// 全局函数重载Point类的操作符和~操作符 —— 定义在类外部
Point operator(const Point self, const Point oth) { ... }
Point operator~(const Point self) { ... }一些限制
有的程序员不喜欢使用重载操作符因为它的特性实在难以琢磨。但实际上它只是在定义函数的基础上又一些限制
基本数据类型只能通过全局函数重载操作符。因为基本数据类型是语言内置的无法自定义。自定义类型这也是最通用的用法 所有支持重载的操作符都可以通过类成员函数重载大部分支持重载的操作符都可以通过全局函数重载有3个例外 ()、[]、-每个操作符重载时形参个数都是固定的按照单目、双目、多目分类形参个数要求如下 单目操作符 双目操作符 多目操作符 全局函数 1 2 - 类成员函数 0 1 0个或多个
以上内容足够正确使用重载操作符。但有些同学会觉得很难理解和正确使用下面一起理解一下重载操作符的本质理解本质之后再回头来看就会发现重载操作符原来...就这
2 重载操作符的本质
重载操作符本质上是特殊的函数。在c中函数具有以下形式
返回值 函数名 (形参列表) { 函数体 }
可以看到函数由四个部分组成返回值、函数名、形参列表、函数体。重载操作符本质上也是函数只是在 函数名、形参列表 两部分具有特殊性另外 调用方式 也很特殊。
函数名
重载操作符的函数名是由operator关键字和操作符符号组成的例如 operator、operator!等等。
形参列表
形参列表的参数数量是固定的具体见下面的表格 单目操作符 双目操作符 操作符-特殊 全局函数 1 (self) 2 (self, 任意类型) - 类成员函数 0 1 (任意类型) 0个或多个 一个没用的小知识 大家可能已经发现了对于同一个操作符而言全局函数重载总是比类成员函数重载多一个参数这个多出来的参数有两个特点 一定是全局函数的第一个形参。类型一定是重载操作符的目标类型。例如 成员函数重载: Point operator(const Point oth) const { ... } 全局函数重载: Point operator(const Point self, const Point oth) { ... } 这里隐藏了一个成员函数的秘密在c中成员函数默认第一个参数是this指针只不过写法上忽略了。大家感兴趣的话可以研究下成员函数的汇编码其中的奥秘就一目了然了。熟悉python语法的同学应该能很容易理解python的类成员函数必须把第一个参数写成self这样才能在函数体内访问成员变量。 调用方式
操作符的使用和函数调用有直观上的差别如何使用操作符大家应该都很熟悉这里就不举例子了。值得一提的是操作符的使用本质上还是函数调用。举个例子用全局函数重载操作符
struct Point {Point(int x, int y) : x(x), y(y) { }int x;int y;
};// 重载Point的“”操作符
Point operator(const Point self, const Point oth) { return Point(self.x oth.x, self.y oth.y); }int main() {Point p1(20, 60);Point p2(2, 5);Point pAdd p1 p2; // 使用Point的“”操作符
}
上面这段代码的汇编代码如下为了方便大家能抓住重点对汇编码做了精简
Point::Point(int, int) [base object constructor]:...ret
operator(Point const, Point const):...ret
main:...mov rsi, rdxmov rdi, raxcall operator(Point const, Point const)...ret
可以看到编译器把Point pAdd p1 p2;这句c代码编译成了call operator(Point const, Point const)也就是调用函数operator(Point const, Point const)。
看到这里大家脑子里会不会闪过一个大胆的想法——在c代码中直接调用函数operator(Point const, Point const)会怎么样就像...
...Point pAdd operator(p1, p2); // Point pAdd p1 p2;
...
然后我们会发现代码竟然可以 正常运行而且对应的汇编代码也一模一样所以操作符也可以通过函数掉调用的方式使用。
前面研究的是全局函数重载的行为那么成员函数重载呢我们一起来看看
struct Point {Point(int x, int y) : x(x), y(y) {}// 重载Point的“”操作符Point operator(const Point oth) const { return Point(x oth.x, y oth.y); }int x;int y;
};int main() {Point p1(20, 60);Point p2(2, 5);Point pAdd p1 p2; // 使用Point的“”操作符
}
对应的汇编代码
Point::Point(int, int) [base object constructor]:...ret
Point::operator(Point const) const:...ret
main:...mov rsi, rdxmov rdi, raxcall Point::operator(Point const) const...ret
编译器把Point pAdd p1 p2;这句c代码编译成了call Point::operator(Point const) const。不难发现全局函数重载和成员函数重载对应的汇编代码的operator符号不一样
形参列表不同。全局函数有两个形参成员函数有一个形参。域前缀不同。全局函数没有域前缀类成员函数汇编后携带了域信息Point。
成员函数重载操作符也可以像函数调用一样使用只不过需要遵守成员函数的调用规则
...Point pAdd p1.operator(p2); // Point pAdd p1 p2;
...
下面做个简单对比 全局函数重载 类成员函数重载 c代码 Point operator(const Point self, const Point oth) { ... } struct Point {Point operator(const Point oth) const { ... }
}; 汇编代码 operator(Point const, Point const) Point::operator(Point const) const 函数式调用 Point pAdd operator(p1, p2); Point pAdd p1.operator(p2);
以上就是重载操作符相对于普通函数的特殊所在除了这几个特殊点其他方面没有任何不同。在使用的时候我们可以对返回值、形参类型、函数体为所欲为
严重警告
尽管规则允许我们直接调用重载操作符但尽量不要这样做因为这样做的话c的NB程度会锐减而且一定会有人在看代码的时候骂你。尽管规则上可以为所欲为还是建议各位保持冷静玩玩儿可以千万不要在项目中写出太超越道德上限的代码。像这样
struct Cat { ... };
struct Dog { ... };Dog operator(const Cat self, const Cat oth) {...return Dog();
}
一只猫加另一只猫得到一条狗