数据结构与算法读书笔记 - 003 - C++如何制作一个类(制作Currency类)

————————————————————
注意点
————————————————————
1,重载函数的默认形参的问题
2,算数类型转换,转换的类型提升方式以及浮点类型到整形变换避免出错的技巧
3,在头文件中直接定义一个函数,什么时候一定要直接定义,什么时候定义了要写inline

————————————————————
基础知识复习
————————————————————

定义函数时候返回类型,形参时候的注意点
感觉这个相当重要而且非常基础,所以提到前面来写

不过其实也就是如何制造形参的复合类型
比较常用的加在形参类型前面的符合类型不过就是
const,&, &&
指针其实都很少用,除非传入的形参就是指针
以及是否是const this*
然后就是返回类型,返回类型主要就是是不是&引用,以及如果真的定义为引用了会发生些什么

由于一共也没有几种复合的方式,我打算以后声明每一个形参之前都问一下自己:
这个形参是否需要/可以是const的
这个形参是否需要/可以是&引用
这个函数的this是否需要/可以是const的
然后这个函数的返回类型是否需要/可以是&引用

返回类型是&引用的时候,在返回的时候会发生什么
这一点感觉读C++ primer时候对于发生的过程也不是特别明了,也许是编译器需要做一些优化所以也没法讲得完全明了么或者就是我自己没读懂了,不过我自己推断应该是这样的:
返回的时候应该是制造一个temp变量的
如果返回类型是&的化应该是这样的:
typename &temp
然后把某个变量绑定到这个temp上,一般来说,是*this
那么就是typename &temp = *this
然后如果需要赋值的话,就是赋值给一个引用(再把temp绑定给一个引用)
typename &变量 = temp

我在最一开始学这一点的时候,比较令我感到新奇和陌生的是,第一,从一个对象到一个引用的过程,实际上是发生在函数返回这个隐性发生的过程中的,第二,以前似乎没用过吧,调用一个函数并且把它的返回值绑定到一个引用上。。。

从一个对象到引用的过渡,发生在函数返回的隐性过程中,慢慢就接受了。。。
返回值是一个引用,其实这是一个没啥用处的返回值啊。想一想,最一开始接触到返回一个引用的返回类型的时候是定义increment或者重载+= 运算符的时候,这种函数使用的目的就是改变那个*this,根本就用不到返回值

当然也许以后会遇到真的需要使用这个返回值的情况。。。

形参什么时候使用const和&
没法分开来说,因为const&是一个很特殊的类型。
摘抄:C++ primer P55
引用的类型必须与其所引用的对象的类型一致,但是又两个例外。第一种例外情况就是在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。尤其,允许为一个常量表达式绑定非常量的对象,字面值,甚至是个一般表达式。

然后根据上面以及下面的叙述可以得出结论:
1,常量引用可以绑定字面值常量,感觉在概念上,即是延长了一个右值的生命周期,不过这里都是常量, 没法改变任何值的
2,没法通过常量引用改变绑定到常量引用上的对象的值,但是可以通过其它方式改变这个对象的值

对于2,即使是常量引用作为形参来使用的时候也是适用的

我要定义一个全局变量,虽然说很多人都说最好不要轻易定义全局变量

#include <iostream>
int x = 10;
void constRefTry(const int &a)
{
   
	std::cout << a << std::endl;
	x = 20;
	std::cout << a << std::endl;
}

int main()
{
   
	constRefTry(x);
	return 0;
}

输出是
10
20

所以说,即使常量引用的是函数的形参,它也要一直追随着绑定在它身上对对象,如果原来的对象被改变了,常量引用,作为这个对象的一个别名,也要被改变

使用常量引用的一个作用,既然它是一个很具有特例性质的一种类型,可以用来直接在传入实参初始化形参的时候,直接传入字面值常量的类型
或者是很单纯地需要const和&的情况,及不想复制传入的形参对象,又不想改变传入对象的值

其实直接用一个很正常的类型,即类型原类型来接受字面值常量,是不是也可以呢,但是限制了传入的类型,如果想传入一个变量,就不得不复制了

那用一个非const的引用呢?非const的引用不必发生复制,但是就没法传入一个字面值常量了

所以const引用同时具有了两种性质,即可以传入字面值常量,又可以避免复制地传入左值

那如果是单独的const或者单独的引用就很好理解了

其实也没有那么多情况。有时候加上const只是一种保险,虽然可能在函数的代码中不会去改变这个对象,但是既然不想改变,那么就在形参的时候就加上const好了。我想这可能是写程序的一种传统吧,在能加上另一层保险的时候就加上另外一层保险,毕竟大多数的程序都很复杂,复杂到普通人很难在半秒之内或仅仅是一瞥就能看清一个函数的结构。所以能加上一层保险就加上一层吧

包括this,如果不想改变this,也在后面加上 const

一开始的时候我对这种”多此一举“的行为还挺反感的,但久而久之,如果不想改变一个对象的值还不加const,反而感觉有点不对头。这就像给一个角色起名字,或是为一个概念起名字,总是想在这个名字中体现这个名字或者概念的全部性质

最后关于函数内变量的生命周期。形参属于局部变量,在函数的右括号”}“结束的时候,会把局部变量全部清除,所以不要返回局部变量的引用,这应该也是primer中说的但是我忘了是在哪说的了,肯定是关于函数返回类型以及其返回过程的原理的那部分了

而且,如果返回的引用绑定的对象不是局部对象,在函数结束的时候被绑定的对象时不会被删除的。有些地方写的感觉这是一个例外一样,但是感觉不像是例外。绑定的临时对象被删除掉了,但是不应该删除被绑定的对象,即使不在函数当中不也应该是这样么

&&右值引用主要是用在类模板处,原理是引用折叠的”逆向工程“(我觉得根据实参推断模板实参即使一项”逆向工程“,在引用折叠处格外明显)
————————————————————
private的权限
在类的定义中–类的函数的定义中,类的函数是可以使用自己类中的private成员的。而”类的用户“是没法使用private的成员的。所以我一直以为只要是使用一个类的对象,就不能使用其private成员(因为我以为的是,在使用这个对象,不就是这个类的用户了么?)。
不过后来我发现如果在定义这个类的时候,如果这个函数使用了自己类的对象,比如在定义类的成员函数的时候使用了相同类的const& 对象作为形参,其实在这种情况下是可以使用这个对象的private成员的,而不用再用相对应的getter函数来获取这个成员。。。使用函数即使是内联的应该也会增大开销吧
————————————————————
析构函数
析构函数再简单的类中根本用不到
我印象里关于析构函数的要点

在删除一个对象的时候调用析构函数,先运行析构函数{}中的内容,然后再依次删除类的成员对象(如果是类类型就调用类析构函数,如果是内置类型就什么都不做直接删除。。。好像是这样的)

调用delete删除一个指针的时候就要调用指针指向的对象的析构函数,所以这个时候还是要运行一下析构函数{}中的内容,有些相关的操作可以定义在这里。(delete指针,指针本身并不会被删除)

如果是定义基类,析构函数一定要定义成虚函数。的确是有些很明确的原因的,而且这些原因也显而易见,但是我一直没有理得太明白所以也说不出来

再就是,也许是最值得注意的一点 - 定义析构函数,如果没有什么往{}中写的,又想定义成简单的内联的,那一定要在声明析构函数的时候,在头文件中,直接定义了 - 即把{}直接写在声明的后面。否则很容易忘了再在源文件中再写一遍而且不是内联的。然后写代码的时候又查不出来,编译的时候就会报错
————————————————————
类型转换:
long -> unsigned -> double

#include <iostream>

using namespace std;

int main(int argc, const char * argv[])
{
   
    cout << "size of int: " << sizeof(int) << endl;//print 4
    cout << "size of long: " << sizeof(long) << endl;//print 8
    cout << "size of unsigned long: " << sizeof(unsigned long) << endl;//print 8
    cout << "size of long long: " << sizeof(
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值