Tags: C/C++

在看视频的过程中,对有些之前不了解、不清楚的地方简单做一记录。

1.基于对象&面向对象

对于Class,可以根据类里是否有指针将其分为带有指针的类和不带指针的类。 这两种类在编写时的思考是有所不同的。根据不同类之间是否有关联,可以分为:

  • 基于对象(Object Based)
  • 面向对象(Object Oritented)

基于对象编程是指多个类之间没有关系,面向对象编程则是指多个类之间有关系(继承、复合、委托)等。

2.代码扩展名

C++代码的扩展名不一定是.h.cpp,有可能是其它扩展名或者直接没有。例如下图中的源码是用.cc表示的。

3.头文件中的防卫式声明

这是一种非常正规的写法。 防卫式声明的用途是消除包含(Include)次序的影响。 同时,由于在头文件中增加了判断,因此对于多次包含同一个头文件的情况,这样可以有效避免重复引用 (第一次引用时正常,第二次发现已经定义了,就直接跳出了)。

4.内联(Inline)函数

内联函数是指函数在类的本体(Class Body)里定义,这样的函数就成为了内联函数”候选”。 至于最终能不能真的成为内联函数,最终要看编译器。 这里的函数本体是指在函数的头文件中声明了函数后接着定义。 在本体外面要想把函数变成inline,在函数的返回类型前面加关键字inline即可。 但正如前面说的,这只是对编译器的“建议”而已,至于它最后能不能成为内联,我们并不知道。

内联函数的好处是执行起来比较快,所以建议能写成内联的函数尽量写成内联函数。

5.类的访问级别

在类中,并不一定非要把所有的publicprivate写在一块,完全是可以交错的。 完全可以写一段公有,写一段私有,再写一段公有,只需要把属性写清楚就行了。

6.构造函数初值列(Initialization List)

正规的写法。构造函数独有的写法。 这样做的好处是效率会高一些。 因为对于变量,它有初始和赋值两个阶段。通过这种初值列的方式可以充分利用初始化这个阶段,从而提升效率。 从最终的结果而言,这和之前那种常规的写法是一样的。但从效率上来说会比传统方法高。

7.构造函数私有

构造函数是可以被放到private区域的。 这样做的结果是该构造函数不能被外界调用,该对象不能被外界创建。 上面是一个Singleton的设计模式。在很多系统提供的API中,都会见到这种用法。 通过调用getInstance()来获取某个对象的实例。

8.常量成员函数

Class类中的成员函数分为会改变类的数据内容的和不会改变数据内容的。 对于不会改变类中数据内容的成员函数,应该加上const使其变为常量成员函数。

如果该加const的函数没有加,那么当用户声明一个静态的类的对象,并调用它的成员函数时就有可能报错。 因为用户指定该变量不能被修改(const),而它的成员函数没有说不能改,这样编译器就会报错。

当调用一个常量对象的成员函数时,如果被调用的成员函数不是const,那么就会报错。

9.引用传递

引用传递相当于传递的是指针,值传递传递的是数据。 因为指针比一般其它的数据类型要小,因此传起来会更快。 所以在参数传递时,尽量都传引用,不要直接值传递。

如果说并不希望函数去修改引用传递进来的对象,则在参数的前面加上const。 表示引用传递到常量。即我把地址传给你,你可以去访问读取数据,但是你不能改数据,因为有const的限定。 这样既保证了传递的速度(传的是指针),又保证了数据的安全(申明变量是const)。

引用传递出了用于函数参数,还可以用于函数返回值。 对于函数返回值,也应该尽量使用引用传递。 当然也并不是所有返回值都适合引用传递。 因为引用传递传递的是指针。 如果说某一个函数在其函数体内新建了一个变量,然后对变量进行了各种操作,最后需要返回该变量。 那么这个情况就不适合以引用传递返回。 因为这个变量的生命周期有关。 这个变量是在函数体内新建的,也就是说这个变量的生命周期只是在执行函数的时候。 当函数执行完成后,这个新建的变量就被自动回收了。 这时如果再返回指向这个变量的指针,那么就会出问题。 返回的并不是这个变量了,因为它已经被回收了。 除了这种情况,都可以考虑返回引用。

10.互为友元

相同class的各个objects互为友元。

11.三个特殊函数

  • 拷贝构造函数
  • 拷贝赋值函数
  • 析构函数

只要类中含有指针,就要自己重写这三个函数。 系统默认提供的拷贝构造函数只是浅拷贝。 浅拷贝可以简单理解为只拷贝指针,深拷贝是拷贝内容,并且新建一个指针指向它。

也就是说系统只会拷贝指针而不会拷贝指针指向的内容。 这样就会导致有两个不同的指针指向同一个内存区域,为后续埋下隐患。 而系统默认提供的拷贝赋值函数同样如此,只会拷贝指针, 这会带来内存泄漏问题。因为相当于被赋值的那个变量中的指针指向了新的地方。 但是它原来指向的那块内存区域现在没有指针指向它了,从而造成内存泄漏。

在拷贝赋值函数中一定要检测是否自我赋值。 一方面是为了提高效率,另一方面是为了不会出错,防止误删数据。 因为拷贝赋值有三步。 第一步是先把自己指向的内存部分清空。 第二步再分配一个足够的和赋值变量大小相等的内存空间。 第三步是把赋值变量里的内容拷贝过来。 如果没有自我赋值检测,那么在第一步把指向的内容清空后, 第二步就没办法继续下去了。因为内容已经被清空了,所以无法获取到内容的大小来新建一块内存。 这其实相当于是把数据删掉了。 因此加上自我赋值检测也可以防止数据误删。

12.复合&委托&继承

本文作者原创,未经许可不得转载,谢谢配合

返回顶部