ctrl+a全选,ctrl+i对齐
ctrl+/ 一起注释
ctrl+z 退回上一步
一些基础的内容:
cout:输出流对象
cin:输入流对象
输入一个i和一个j,然后输出i+j的和:
值不变的原因:
值传递,a和i是两段内存空间,被调不能修改主调,所以i和j不变
指针的间接访问:
注意:下面传的是地址
必须初始化,不然没法自己识别类型
10.8是double类型,10.8f才是float类型,所以结果是8
改成引用:相当于某个变量的别名,此时n就是i的别名(此时被调函数可以修改主调函数)
练习:交换ab
内联函数
拆分:
某个函数被声明为内联函数,则该函数的main函数前一定要有定义
内联函数:编译器将该函数的执行代码在引用处加以展开
默认形参放声明里,不放定义里
函数重载
同名不同参:
编译器选择了和10,20类型匹配的第一个函数调用
两个函数都符合,不知道调哪个
模棱两可的,但是选择了第一个
因为第二个函数引用的形式,其实是企图对i进行修改的,但是i是个常量const修饰,所以他选择了第一个
因为*p前没有const,但是i只能读不能写,p想要的是既能读又能写的,所以报错了
这样是可以的
只读不写
既能读又能写
没有下面的那个函数,那么也可以勉强选择上面的那个传参
抽象:数据抽象和行为抽象
封装
抽象的
具体的
上面是声明,下面是定义
注意:
如果是c.hour就会报错,因为是私有的
一般把类的成员设置为私有的,封装的函数设置为公有的
下面这两种方法也都可以:
一般把公有写在前面,私有写在后面
例题:求圆环的面积
或
::表示area是circle这个类里面的
规范写法:
struct默认都是公有,class默认都是私有
调用带参的函数:
调用不带参的函数 :
最后整理一下:构造函数
赋值改成初始化-只能用在构造函数中 (初始化效率高)
可以写成另一种形式
奇葩写法: (赋值构造或者拷贝构造)
第一种情况:
要是没有下面的函数,c2调的就是复制c1
要是有下面的函数(复制构造函数),c2调的就是下面的,但是结果都是一样的。
第二种情况:
第三种情况:
fm()是匿名对象
总结:复制构造函数的形参是本类的常量
补充:析构函数
类似于出栈(后入的先出)
继承
多态
作业:
组合
has-a型(有一个)
两点构成一条直线
完整代码:(带参构造)
另一种方式:(复制构造)
结果为:
前向引用声明:(只适用于指针或者引用)
例如:
类图:
公有的前面是+
私有的前面是-
作用域
标识符具有类作用域:
命名空间作用域:
进阶:可以进行嵌套
改一下:
没名字的命名空间
全局命名空间作用域:
可见性:
作用域是彼此包含的
对象的生存期
例1:
例2:
调用一下foo
例3:
例4:
例5:
如果没有这个static,那他变成动态的了,每次调用都要申请一次空间,所以结果是一样的,都是0
匿名对象的生存期问题
给别名之后,销毁在end之后,不是因为变成了动态,而是生存期延长了
左值和右值:
左值:是变量,能放在赋值运算符的左边,lvalue
static int i;也是变量,是只读变量
右值:是常量,只能放在右边,不能放在左边的,rvalue
&i可以 &100不可以
注意:所有的匿名对象都是右值(&100)
右值引用:为了运行更快(必须初始化,=后面的值必须是匿名对象-临时对象)-----相当于把右值转换成左值
因为showTime函数要求既能读又能写
所以要是写成const Clock &ref = 。。。。这样写不行,因为这样是左值。
通过右值引用,可以给这个没名字的地方(匿名对象)改值
string的用法
用法1:
结果是HelloWorld!
用法2:好处就是开辟足够大的空间,不浪费
vector的用法
双向链表(有前驱有后继)
deque用法
c++里面可以在括号里面定义int i
但是这个i只能在for循环里面有作用
c++写法:base range for (:后面的必须是容器,不能是指针*p里面的p)
类的静态成员:不为本类对象所特有,为本类对象所共有
公司改名了,改一个所有的都变了
进阶版:类名双冒号
后面的也都改成类名双冒号
类的静态成员函数(变成私有了,加static)
类名双冒号调(因为有static),
static string company;加了static就只开辟一个空间了,在外面开就是下面那句
静态成员:没有对象的时候还能调(类名双冒号调)
例子:统计demo类型的个数
具体代码为:
结果为0 2
结果为0 2 12 2
结果为0 2 13 2
d3那行调复制构造
设计模式
单例模式
类对象只能有一个
getIntance函数的作用是创建个地址然后通过指针传出来
具体代码:
p和q指的是同一个对象,都是对一个
进阶一下:
用const修饰的类成员
static在这里
this指针只存在于类的非静态成员函数中
类的常成员
不能写set
因为set是要改,可是c1是const修饰的,会报错
注意:都是成员函数
(const double pi;)
两端内存空间不一样
解决办法:
类型转换多态
四种
static_cast:两种不相关的类型,类似于double转int
const_cast:去原来的const属性的
剩下两个用于指针转换
写到外面去:
数组:避免越界
数组的遍历
是带参函数和复制函数传过去的数字:
用vector的方法:容器
改写:
练习:逆序
记得包头文件
包了algrithm头文件后里面已经有写好的算法,直接调就行
部分逆序
排序
cplusplus.com - The C++ Resources Network这个网站里啥都有
指针:降低程序耦合性
空指针
早期NULL和0是一个东西
nullptr代表空指针
函数指针
如何调用
或者
例子:打印数组
例子:打印369或者24680
例子:快排
或者(注意这里用了reinterpret_cast类型转换多态,因为是指针转换转换void*的
拓展:lamda表达式(代替短小的回调函数)
将之前所有声明的参数都进行捕获,可修改
使用lamda的完整快排代码:fn(int)的int表示参数是整型的意思
动态内存分配:相当于malloc和free
例子:malloc默认返回的就是void *类型
另一种写法:(这个要调用构造函数和析构函数)(区别就是这个)
初始化后
因为*p++指向了另外一段空间,因为它实际上已经加完了,但是表面上输出的还是原先的,因为是后++,所以已经是另外一段空间了,还回去的和一开始申请的不一样了,相当于内存泄漏。
例子:填写斐波那契数列
或者
例子:斐波那契扩容,从10变成20
打印完10个的先不着急释放,先变成20,复制过去,复制完就把10的空间释放,然后再把10后面的数列传过来,然后打印,最后防止野指针赋一个nullptr,然后再把20的释放
这样写是因为前面的i是从0开始的,但是fib函数的参数是项数,是从1开始的
补充:指针的sizeof是8,strlen看的是有效字符个数,不包括\n
string类代码:
记得包头文件
加一个计算字节的
改写:把赋值的写在冒号后面
写一个追加的函数在hello后面加world
m_p = q;是为了防止m_p变成野指针
用重载的方式写:(要重新申请空间)要记得原来的参数还有一个String &this
传参传自己也行:
写赋值函数:再写一个assign的函数(delete是在销毁原先的空间)
+1加的是\n
重载一下:
完善一下:
类似于这样没意义,自己给自己赋值
加一个析构函数:防止内存泄漏
写一个复制构造函数:
浅复制构造函数(会出错):因为复制构造函数和构造函数指向了同一个空间,复制雅瑶申请一块空间,所以要析构,other.m_p原先的,括号外的m_p是新的,复制出来的s2要先析构,s1也要销毁,这样的话同一块空间就会被析构两次,会出现double free(程序崩溃)的错误。
深复制构造函数:重新开了一个空间
写一个链表类
头插完整代码:
括号里的n是node的value的值
show函数换个方法写:
头插基础上显示链表大小和是否为空
尾插
在上述函数基础上(挨着头插写)加一个尾插函数
main函数里面调一下
头删(挨着尾插写)
在main函数里调
尾删(挨着头删写)
加一个析构函数
或者
复制构造函数
other是老的pHead是新的
浅复制指向了同一个节点(析构函数的时候把链表都析构了,上面的l的phead就变成了野指针)
深复制(让新链表先是空的,然后开始撸原先的链表,可以得到data,然后在新的链表玩尾插,把数据传过去即可)
main函数
继承
这就是类的继承关系,蛇也是类,爬行类动物(已有的)也是类
代码:
只有一个base,单继承
多继承
直接基类和间接基类
补充:
public继承方式,会影响以后的权限
派生里面有(吸收基类成员,改造基类成员,添加新的成员)
继承了基类的所有属性(吸收基类成员),除了基类的构造和析构之外
改造基类成员(对他的行为进行了修改,fn相当于咬的动作,按自己的方式咬)
不是重载,是隐藏,基类的fn此时被隐藏了,派生类把基类的名字相同,给他挡住了
两个同名函数要是在一个作用域里才讨论重载的问题
添加新的成员
类型兼容规则
都用的公有派生类对象
因为p是基类的指针
sizeof
sizeof大小是8,看基类和自己的private里面的变量大小加起来
执行顺序
代码例子:
自己写一个日历的代码:(在clock基础上)
下面这样写的比较好
基类指针指向派生类对象
访问权限
qt制作
查询手册方法
/home/linux/Qt5.9.0/5.9/gcc_64/bin
./assistant
打开下面的手册
代码:
这样改写好点
加按钮
窗口写字
进阶版:(两个按钮)
拓展:
前面的都是底层的,现在开始正式
重新创建工程:
explicit禁止编译器做隐式转换
.ui就可以直接设计界面
.h
练习:设计一个窗口
水平布局(垂直布局同理)
要想窗口里的东西随着窗口大小改变而改变,就点空白的地方然后右键点击水平或者垂直(一般是垂直)就可以了
效果
QT信号与槽机制例子
.h文件
.c文件
记得把白框命名成editHello:(同理下面的白框叫editWorld)
然后要把按钮和白框的文字用connect函数连接起来:
还可以写成:
写下面这个槽函数都不用写了
效果:
补充:取地址怎么写?
练习:移动滑块,显示数字
效果:
练习:移动滑块最下面的sbin box也显示数字
练习:改动最下面的sbin box的数字,让上面的滑块也跟着数字移动
或者
或者强转:
用定时器:每过100ms,progressbar都要加1,直到加满为止qtimer
this是窗口,如果窗口被销毁了,就会自动调用timer的析构函数销毁
显示当前时刻:
让时钟动起来(让定时器一秒触发一次)qtime
随着时间动起来
多态性
绑定
求和函数
换种写法:
复数相加:(实部加实部,虚部加虚部)
换种写法:
比大小排序
例:
通过引用可以返回
如果函数返回值是引用,就可以当左值
如果函数返回值是一个对象,则只能做右值
前++和后++(前++返回的是加之后的要加&,后++返回的是加之前的)
赋值
取地址
拼接字符串
另一种拼接
后面的const修饰的是this指针
深赋值(好一点)
浅赋值(double free)
虚函数(非常重要)->可以实现包含性多态
上面的写法不太好,用虚函数更好(虚关键字必须加到基类,这两个函数必须同名且同参)
这样可以实现输入1调用基类,其他调用派生
算字节
虚表(虚函数表)
如果基类是虚的,那么派生类也是虚的,因为可以继承
先去基类找函数,虚函数要去查虚表,不虚函数直接调
如果基类没有虚函数,但是他自己有虚函数,那么调的就是他自己的
虚表长这样:
他自己没有f5,所以f5没有覆盖,还是base
虚析构函数(可以避免内存泄露)
注意:
析构函数可以是虚析构!!!
下面的cat派生类,必须将基类的纯虚函数写出来,不然不写出来的话,cat类依然被认为是抽象的
泛型编程(模版)要写到头文件里面
函数模板
在这个里面printArray根本不是函数,是函数模板,这个T会被自动当做double去用
例子:写一个选择排序
如果既有模板又有下面这个特化后的函数,那么在调用的时候调的是特化后的(很偏心)
类模板(包括容器类...)
写在外面的算声明,要放在头文件
把List类也改写一下: