C++面向对象高级编程(上) 第一周 侯捷

时间:2020-12-19 19:49:11

头文件与类声明

 

头文件中的防卫式声明

#ifndef _FILENAME_
#define _FILENAME_
//...
#endif

扩展:为什么要添加防卫式声明(防止由于同一个头文件被包含多次,而导致了重复定义。

https://www.cnblogs.com/xyq10612/p/5910933.html

 

头文件的布局

#ifndef __COMPLEX__
#define __COMPLEX__

#include<cmath>

//前置声明
class ostream;
class complex;

complex&
   _doapl(complex * ths, const complex);


//类声明
class complex {

};

//类定义
complex::function....

#endif

 

模板简介

C++面向对象高级编程(上) 第一周 侯捷

 

 

构造函数

 

内联函数

1、你的函数在你的类本体里面定义,那么你就是一个inline。

2、如果你的函数太复杂,就没有办法inline

C++面向对象高级编程(上) 第一周 侯捷

3、即使你把函数写在了class里面,最后的结果是否inline,是由编译器去决定的。

4、不在类里面定义的函数,你也可以把他inline,如上图(2-2)。写了一句:inline double

 

访问界别(access level)

1、什么东西应该是private的呢?   应该是数据的部分,因为我们的数据应该是封装起来的,不要被外界任意看到。

C++面向对象高级编程(上) 第一周 侯捷

2、public 和private是可以交错出现的。也就是说,你的class body很大,你可以先些一段public,之后写一段private,后面想到了什么,可以再插一段public,之后还可以在写private

 

构造函数(constructor)

1、如果你想要创建一个对象,有一个函数会被自动的调用起来,这个函数就是构造函数。

2、下图用动态的方法去创建一个对象,得到的会是一个指针。

C++面向对象高级编程(上) 第一周 侯捷

3、构造函数的函数名和类名相同

4、他可以有参数,参数可以有默认值(default argument)

【有了默认值,当你创建对象的时候,如果没有指明参数值,则用默认值】

5、他没有返回值类型

C++面向对象高级编程(上) 第一周 侯捷

6、初值列——只有构造函数享有这个功能

C++面向对象高级编程(上) 第一周 侯捷

上图把r设到re中去,把i设置到im中去

7、不写初始列就不是练家子的原因:一个变量,它的数值的设定有两个阶段,一个是初始化,一个是赋值。如果你不写初始列,直接在函数体里面赋值,证明你放弃了初始化的阶段,这样的话赋值的时间点会晚一些,效率会差一些。

C++面向对象高级编程(上) 第一周 侯捷

8、你不可能在你的程序里面去调用构造函数,你只可能去创建对象。创建对象时,构造函数会自然而然被调用起来。

9、不带指针的类,大部分不用写析构函数。

 

构造函数可以有很多个-----重载(overloading)

C++面向对象高级编程(上) 第一周 侯捷

两个构造函数real的名称相同,但是编译器是可以分清谁是谁的,所以可以重载。(编译器通过函数名,里面的参数名,参数类型等一系列的信息来区分同名的构造函数)

1、在c++中,同名(其实对于编译器来说是不同名的)的函数可以存在。

2、函数重载常常发生在构造函数中。

3、由于目前拥有的构造函数已经有默认值了,你还是可以去重载写出其他的构造函数,但是你新写的构造函数没有默认值就不行,会引起冲突。如下图,2就不会被调用

C++面向对象高级编程(上) 第一周 侯捷

 

 

参数传递与返回值

 

把构造函数(ctors)放在private区域里

当不允许被外界创建对象的时候,把构造函数放在private里面。那这个类有什么用?

下图是一个有名的设计模式singleton就用到了把ctors放在prvate里

C++面向对象高级编程(上) 第一周 侯捷

扩展:懒汉模式he饿汉模式

https://blog.csdn.net/hj605635529/article/details/70172842

 

常量成员函数(在函数()的后面{}的前面,写一个const )

该函数的意思是不会改变传入的数据的内容,如下图:

C++面向对象高级编程(上) 第一周 侯捷

C++面向对象高级编程(上) 第一周 侯捷

上述类中,如果函数real 和函数imag没有加上const,则使用者希望不改变传入值时,给自己的调用前面加上了const程序会报错,因为类中的函数没加上const代表你传入的值可以改变。

因此,类中的real函数和imag函数需要加上const。此例说明,在设计函数的时候,要充分考虑各种情况。

const出现在对象或者变量的前面,说明我的对象或者变量是不可改动的。e.g C++面向对象高级编程(上) 第一周 侯捷

参数传递:pass by value vs pass by reference

1、Pass by value 是把数据整包的传过去,压入到栈中,所以尽量不要pass by value

2、引用在底层就相当于一个指针,所以传递引用就相当于传递指针那么的快

3、传引用 to const 可以保证传递速度快,而且你不会改变我传入的值。如下图:

C++面向对象高级编程(上) 第一周 侯捷

 

返回值传递:return by value  vs return by reference

C++面向对象高级编程(上) 第一周 侯捷

 

friend友元

可以直接拿你private的数据

C++面向对象高级编程(上) 第一周 侯捷

 

同一个class内的各个对象互为友元(friend)

C++面向对象高级编程(上) 第一周 侯捷

直接获取了私有数据

 

对于类,老师会特别注意什么地方呢?

1、数据放在private里面

2、参数和返回值尽可能使用reference来传

3、类中的函数,应该加const的就要加,否则使用者在使用的时候会报错。

4、构造函数的初始列要尽量去用。

 

什么情况下不能return by reference

函数运行结束的时候,函数内创建的变量会被销毁。如下图,就不能return 参数三的reference

C++面向对象高级编程(上) 第一周 侯捷

 

 

操作符重载与临时对象

操作符重载-1,成员函数,this

1、在C++中,操作符就是一种函数,是可以让你重新定义的。

2、所有的成员函数一定带着一个隐藏的参数this,谁调用我的成员函数,这个隐藏的this就指向它(比如下图中的this)

C++面向对象高级编程(上) 第一周 侯捷

 

return by reference 语法分析

  1. 如果用reference来传的话,传递者无需知道接受者是以什么形式接收(也许是by value,也许是by reference)

C++面向对象高级编程(上) 第一周 侯捷

C++面向对象高级编程(上) 第一周 侯捷

(操作符要考虑使用者的连串使用情况C++面向对象高级编程(上) 第一周 侯捷

 

全域函数(不是在class中声明的函数,如下图所示)

C++面向对象高级编程(上) 第一周 侯捷

 

操作符重载-2 非成员函数 无this

temp object临时对象  typename ();(例如. int ();)

C++面向对象高级编程(上) 第一周 侯捷

 

因为complex是函数中创建出来的,所以你的返回值不是by reference,而是by value。

临时对象:临时想要的东西,我不想给你名称,他的生命到下一行就结束了。

编译器如何区分加减和取正负呢?  ---看参数就知道了,只有一个参数的,肯定是取正负

C++面向对象高级编程(上) 第一周 侯捷

 

操作符重载 非成员函数

C++面向对象高级编程(上) 第一周 侯捷

“<<” out put operator 不要想把这种操作符写成一个成员函数

(操作符有两种写法,一种是成员函数的写法,一种是非成员函数的写法),这个操作符只能考虑全局的那种写法

因为如果你返回的是引用,那么你就是要把返回值赋值给”<<”左边的”cout”,可是”cout”是标准库的东西,你不可能赋值给他,所以,对于”<<”操作符,无法写成成员函数,其他的操作符写成成员函数或者非成员函数都是可以的,但是单单这个不行。

 

函数的返回值类型没有用void,是因为有可能使用者会使用连续的输出,如下图

C++面向对象高级编程(上) 第一周 侯捷     C++面向对象高级编程(上) 第一周 侯捷