浅谈运算符重载与友元函数
发布日期:2022-02-07 06:39:45 浏览次数:2 分类:技术文章

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

Vector强化版

大纲:

1. 运算符重载
3. 友元函数
4. 思考一个问题

先把Vector类的代码放出来

相比上次的Vector省略了一些

// Vector.h#ifndef VECTOR_H#define VECTOR_Hclass Vector{private:    int x;    int y;public:    void show() const;};#endif
// Vector.cpp#include "Vector.h"#include 
void Vector::show() const{ using namespace std; cout << x << "," << y << endl; return ;}。。。。。。

如果要把一个矢量相加减

你是否梦想着可以用下面的代码来实现呢?

//test.cpp#include "Vector.h"#include 
using namespace std;int main(){ Vector v1(2,3); Vector v2(3,4); Vector vp; Vector vm,vm2; vp = v1 + v2; vm = v1 * v2; vm2 = 3 * vm; cout << v; return 0;}

可是,Vector类对象并不是普通的内置类型

计算机并不知道如何将他们相加相乘
更不知道如何用cout将这个类输出
这个时候,全都需要我们自己定义运算符

运算符重载

两个double类型的数据可以用运算符+相加

两个int类型的数据也可以用运算符+相加
诶,+号就像函数一样
可以根据不同的参数类型执行不同的操作
其实,运算符重载和函数重载是一样的呢
再其实,运算符其实就是个函数
下面先放出一个运算符重载的实例

// 函数原型Vector operator+(Vector v1,Vector v2);// 函数定义Vector operator+(Vector v1,Vector v2){    Vector temp;    temp.x = v1.x + v2.x;    temp.y = v1.y + v2.y;    return temp;}

在这个函数定义中,

+号在函数里用了operator+表示
注意:这里说明了,运算符是可以有两种表示方式的
一种是运算符表示法: v = v1 + v2;
y一种是函数表示法:v = operator+(v1,v2);
然后其他的东东和普通的函数时一样的
可是,这个函数是不能用的

还记得以前说到的,

非成员函数,是不能够访问类的私有成员的
要解决这个问题
1. 在类中定义运算符重载
2. 友元函数

类中运算符重载与普通运算符重载区别

还记得以前说到的

类成员函数,会隐式的传递this指针
下面还是先给一个类中定义运算符重载的例子

Vector Vector::operator+(Vector v1){    Vector temp;    temp.x = v1.x + x;    temp.y = v1.y + y;    return temp;}

区别:

1. 使用作用域解析运算符
2. 少传递了一个参数,原本需要两个操作数的+
只传递了一个对象?

在类中,会隐式的传递自身作为运算符的一个操作数

如:v = v1 + v2
用函数表示法可表示为
v = v1.operator+(v2);

友元函数

对上面的问题,还有一种解决方案

虽然非成员函数无法访问类的私有成员
但我可以通过一种特殊的方式
让非成员函数获得访问私有成员的特权
友元函数!!

友元函数的语法要求有两个:

1. 函数的原型前面加上friend关键字
2. 函数原型必须放在类定义内部

下面给例子

// 函数原型class Vector{    ...public:    ...    friend Vector operator+(Vector v1,Vector v2);}// 函数定义Vector operator+(Vector v1,Vector v2){    Vector temp;    temp.x = v1.x + v2.x;    temp.y = v1.y + v2.y;    return temp;}

函数的调用方式略有不同

v = v1 + v2;
实际上是这样的函数调用
v = operator+(v1, v2);

其他操作的实现

乘法和加法类似

也有友元版运算符重载
和类内运算符重载两种形式
不过有一个需要思考的
vm2 = 3 * v2
这个该怎么办呢?

在类内运算符重载中

二元运算符的第一个操作数是调用对象本身
第二个操作数是函数参数
如:v = v1 + v2
用函数表示法可表示为
v = v1.operator+(v2);

vm2 = 3 * v2

只有通过定义一个友元函数才能够解决
因为 3 不是一个对象,
无法调用对象内的运算符函数来计算
只能够通过友元函数来实现

// 函数原型class Vector{    ...public:    ...    friend Vector operator*(int d ,Vector v);}// 函数定义Vector operator*(int d ,Vector v){    Vector temp;    temp.x = v.x * d;    temp.y = v.y * d;    return temp;}

思考

  1. 上面的运算符重载能否实现以下操作

    v = v1 + v2 + v3 + v4;

  2. 运算符重载,是否能够重载任意运算符?

  3. 重载能否改变现有的运算规则

    (比如把两个int类的+法自定义)

  4. 如何实现<< 的运算符重载从而实现

    cout << v;

1.

可以

假设这里用的是类内的运算符重载
根据+号从左往右结合
先算v1 + v2
v = v1.operator(v2) + v3 + v4;
然后根据函数定义
该函数返回一个Vector对象
也就是说
v1.operator(v2)本身就是一个Vector 对象
然后这个对象与v3结合,再使用+号
v = v1.operator(v2).operator+(v3) + v4;
后面以此类推
关键是在该运算符函数返回对象(当然也可以返回对象的引用)

2.

还是有很多限制的

比如:
1. 运算符操作数至少一个数是用户自定义的类型
2. 不违反现有的句法规则
3. 不创造新的运算符
4. 一部分运算符不可以重载
一部分运算符只能在类内作为类成员函数重载
一部分运算符类内类外均可

具体的可以自行了解

当然加减乘除都是类内类外均可的

3

哎呀……上面不小心回答完了

4

先放例子

// 函数原型class Vector{    ...public:    ...    friend ostream & operator<<(ostream & os, const Vector & temp );}// 函数定义ostream & operator<<(ostream & os, const Vector & temp ){    os << temp.x << "," << temp.y << endl ;    return os;}

详细解释看 c++ primer plus p392 - 394吧

不大好解释呢
反正……cin是一个ostream类的对象
所以要想
cin << v;
函数的形参列表就必须与上面对应
(见函数定义)

一些比较好的博客

转载地址:https://blog.csdn.net/wyfwyf12321/article/details/54745772 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:继续实现Vector类
下一篇:关于传值传引用,const的使用

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月13日 12时25分08秒