头文件与类声明
头文件中的防卫式声明
#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
模板简介
构造函数
内联函数
1、你的函数在你的类本体里面定义,那么你就是一个inline。
2、如果你的函数太复杂,就没有办法inline
3、即使你把函数写在了class里面,最后的结果是否inline,是由编译器去决定的。
4、不在类里面定义的函数,你也可以把他inline,如上图(2-2)。写了一句:inline double
访问界别(access level)
1、什么东西应该是private的呢? 应该是数据的部分,因为我们的数据应该是封装起来的,不要被外界任意看到。
2、public 和private是可以交错出现的。也就是说,你的class body很大,你可以先些一段public,之后写一段private,后面想到了什么,可以再插一段public,之后还可以在写private
构造函数(constructor)
1、如果你想要创建一个对象,有一个函数会被自动的调用起来,这个函数就是构造函数。
2、下图用动态的方法去创建一个对象,得到的会是一个指针。
3、构造函数的函数名和类名相同
4、他可以有参数,参数可以有默认值(default argument)
【有了默认值,当你创建对象的时候,如果没有指明参数值,则用默认值】
5、他没有返回值类型
6、初值列——只有构造函数享有这个功能
上图把r设到re中去,把i设置到im中去
7、不写初始列就不是练家子的原因:一个变量,它的数值的设定有两个阶段,一个是初始化,一个是赋值。如果你不写初始列,直接在函数体里面赋值,证明你放弃了初始化的阶段,这样的话赋值的时间点会晚一些,效率会差一些。
8、你不可能在你的程序里面去调用构造函数,你只可能去创建对象。创建对象时,构造函数会自然而然被调用起来。
9、不带指针的类,大部分不用写析构函数。
构造函数可以有很多个-----重载(overloading)
两个构造函数real的名称相同,但是编译器是可以分清谁是谁的,所以可以重载。(编译器通过函数名,里面的参数名,参数类型等一系列的信息来区分同名的构造函数)
1、在c++中,同名(其实对于编译器来说是不同名的)的函数可以存在。
2、函数重载常常发生在构造函数中。
3、由于目前拥有的构造函数已经有默认值了,你还是可以去重载写出其他的构造函数,但是你新写的构造函数没有默认值就不行,会引起冲突。如下图,2就不会被调用
参数传递与返回值
把构造函数(ctors)放在private区域里
当不允许被外界创建对象的时候,把构造函数放在private里面。那这个类有什么用?
下图是一个有名的设计模式singleton就用到了把ctors放在prvate里
扩展:懒汉模式he饿汉模式
https://blog.csdn.net/hj605635529/article/details/70172842
常量成员函数(在函数()的后面{}的前面,写一个const )
该函数的意思是不会改变传入的数据的内容,如下图:
上述类中,如果函数real 和函数imag没有加上const,则使用者希望不改变传入值时,给自己的调用前面加上了const程序会报错,因为类中的函数没加上const代表你传入的值可以改变。
因此,类中的real函数和imag函数需要加上const。此例说明,在设计函数的时候,要充分考虑各种情况。
const出现在对象或者变量的前面,说明我的对象或者变量是不可改动的。e.g
参数传递:pass by value vs pass by reference
1、Pass by value 是把数据整包的传过去,压入到栈中,所以尽量不要pass by value
2、引用在底层就相当于一个指针,所以传递引用就相当于传递指针那么的快
3、传引用 to const 可以保证传递速度快,而且你不会改变我传入的值。如下图:
返回值传递:return by value vs return by reference
friend友元
可以直接拿你private的数据
同一个class内的各个对象互为友元(friend)
直接获取了私有数据
对于类,老师会特别注意什么地方呢?
1、数据放在private里面
2、参数和返回值尽可能使用reference来传
3、类中的函数,应该加const的就要加,否则使用者在使用的时候会报错。
4、构造函数的初始列要尽量去用。
什么情况下不能return by reference
函数运行结束的时候,函数内创建的变量会被销毁。如下图,就不能return 参数三的reference
操作符重载与临时对象
操作符重载-1,成员函数,this
1、在C++中,操作符就是一种函数,是可以让你重新定义的。
2、所有的成员函数一定带着一个隐藏的参数this,谁调用我的成员函数,这个隐藏的this就指向它(比如下图中的this)
return by reference 语法分析
- 如果用reference来传的话,传递者无需知道接受者是以什么形式接收(也许是by value,也许是by reference)
(操作符要考虑使用者的连串使用情况 )
全域函数(不是在class中声明的函数,如下图所示)
操作符重载-2 非成员函数 无this
temp object临时对象 typename ();(例如. int ();)
因为complex是函数中创建出来的,所以你的返回值不是by reference,而是by value。
临时对象:临时想要的东西,我不想给你名称,他的生命到下一行就结束了。
编译器如何区分加减和取正负呢? ---看参数就知道了,只有一个参数的,肯定是取正负
操作符重载 非成员函数
“<<” out put operator 不要想把这种操作符写成一个成员函数
(操作符有两种写法,一种是成员函数的写法,一种是非成员函数的写法),这个操作符只能考虑全局的那种写法
因为如果你返回的是引用,那么你就是要把返回值赋值给”<<”左边的”cout”,可是”cout”是标准库的东西,你不可能赋值给他,所以,对于”<<”操作符,无法写成成员函数,其他的操作符写成成员函数或者非成员函数都是可以的,但是单单这个不行。
函数的返回值类型没有用void,是因为有可能使用者会使用连续的输出,如下图