关于传值传引用,const的使用
发布日期:2022-02-07 06:39:45 浏览次数:2 分类:技术文章

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

实现Vector 类(四)

这里主要做一些优化

传入参数属性的选择

拿其中的一个函数作为例子

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

在这里,我们传入了一个v1对象

当我这样子调用

Vector v1(2,3);Vector v2(3,4);Vector v;v = v1 + v2;

相当于这样子

v = v1.operator+(v2);
v2作为参数传进函数中
聪明的你们当然知道这是传值引用
所以,v2传入函数时会创建一个临时对象
然后用这个临时对象参与运算
最后返回一个另一个临时对象temp
退出函数时,v2形成的临时对象执行析构函数被销毁
临时对象temp赋值给对象v后被自动销毁

选择:

按值传递,按址传递,按引用传递
按值传递需要创建临时对象
需要消耗额外的计算与存储资源
最好是传入指针或引用
当然在C++中引用是更好的选择

因此我们可以这样修改

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

传入参数属性的选择(二)

按值传递和按引用传递(暂时不讨论指针了)

按值传递的最大优点是不会修改原来的数据
现在我们传入了引用
如果操作有失误,可能会使得源数据被修改
这时候我们可以考录传入const的引用
因此我们可以这样修改

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

这样子传递参数,就能够防止源数据被修改

(当然如果本来就要修改的话那就不要const罗)

关于构造函数的使用技巧

我们回顾下Vector我们定义的构造函数的原型

Vector(int a, int b);
事实上
构造函数不仅仅在初始化的时候可以调用
它本来就可以当成一个函数直接在类里使用
所以
上面的例子可以进一步优化

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

这里构造函数Vector直接根据参数生成一个临时对象

然后把这个临时对象返回。
这样子能够使整个函数更为简洁
可读性也更强

关于const的使用

刚刚讲到一个传入参数用const

还有一个作用
而且是一个很重要很重要的作用
我们可以像创建常量一样创建常量对象

Vector v1(2,3);const Vector v2(3,4);

这样子,const的使用使v2成为常量对象

那可以这样子吗?

Vector v1(2,3);const Vector v2(3,4);Vector v;v = v1 + v2;

这样子的调用

v = v1.operator+(v2);
参照
如果这样
Vector operator+(Vector & v1);

v2是个常量,但是函数参数却不是常量引用

如果成功传递,将会导致原本是常量的内容被修改!
因此这样的参数传递是不能过的

按值传递

由于改变的是临时变量
是不是const都没关系
按引用传递
由于会改变源数据
普通引用的参数只能传入普通的变量
const&的参数
既能接受普通变量又能接受const变量
兼容性++

关于const的使用(二)

Vector v1(2,3);const Vector v2(3,4);Vector v;

这样的声明

我能否这样做
v = v2 + v1;
和刚刚的例子比起来,好像只是换了下顺序
但是他的函数调用形式变了
v = v2.operator+(v1);

好像也没什么问题?

注意!这里的v2是常量对象

复习以前说过的this指针

this指针在对象中指的是
调用对象本身的指针
复习const成员函数
在成员函数后面加const
相当于给this指针加上了const
防止对象成员函数修改自身数据

复习完,再看看const对象

const对象
不就是自身数据不会被修改的对象吗
它的数据只要初始化之后
就不能够被修改
因此const对象里的this指针
应该全都要是const * 类型的
可是这里的运算符重载函数并不是const成员函数
里面的this指针不是const的
所以上面的调用
v = v2.operator+(v1);
是行不通的

因此,只要是不需要修改自身数据

常量对象可能执行的类方法
都需要用const成员函数
修改方案如下:

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

如果对用一个函数有两个不同的版本

一个是const成员函数
一个不是const成员函数
那么常量对象调用函数将会执行const成员函数
普通对象将会调用const成员函数
这也个根据this指针const属性不同
导致函数形参列表不同特征标不同
然后函数重载的一个实例

总结

  1. 参数属性的选择,
    1. 按值传递,按引用传递
    2. 是否使用const
  2. 尽可能地使用const,能增强类的兼容性(对常量对象的兼容)
  3. const成员函数的理解(this指针的const属性)
  4. 构造函数的使用,能够大大降低程序的复杂度

至此,一个简单的Vector类

算是出来了

我们已经详细讲解了+号的重载
以及它的优化
之后我们就可以加上

+

*

来用最舒服的方式
实现矢量之间最基本的运算
通过重载
>, >= , < , <= ,==
可以实现矢量之间的大小比较
还可以重载
+=, -=,*=
使得矢量的使用更加的接近普通变量
当然,还可以根据矢量的特征
自己在定义多几个矢量的类成员函数
比如计算两个矢量之间的角度
还可以在矢量类私有成员中加上长度
并在初始化时自动计算长度
从而在类内部调用长度的时候更为方便

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

上一篇:浅谈运算符重载与友元函数
下一篇:linux 入门

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月11日 20时59分16秒