C++复健1(未整理)
C++复健(侯捷)
overloading (重载)
重载的条件:
同名
同作用域
不同的返回值
或者不同的参数(形参)
同名:其实在编译器来看是不同名的
作用域:一个类内,一个全局域内,一个函数域内
当构造函数放在私有中:
设计模式:Singleton
外界不能创建这个类
但是我们可以通过这个类提供的外界接口。
示例:
1 | class A{ |
成员函数,内联(inline)定义,调用是最快的
但内联是编译器决定的,写的定义过于复杂就不能一定是内联函数
我们在类外定义函数实现的时候:需要inline在最外进行修饰,才有可能修饰成内联函数
构造函数:初始化值最好使用初始化列表的方式
常量成员函数
修饰符:const
要确定,是否要更改其中对象中数据,
如果要不需要更改 ,那必须需要修饰成员函数 添加const修饰
因为这是正规的正式合法的修饰,不加说明你是学习C++的杂牌军
const的意义
在使用该类的途中如果使用了const修饰,你却没有给这个函数修饰,编译器会报错
所有的成员函数都隐藏着一个参数 this; 这个this是调用这个成员函数的对象的指针
示例:
运算符的重写
1 | //表面写法 |
可以理解的是 this指针,其实就是,多个对象之间,调用的函数都是同一份 的调用依据
这里跟上一句话:对象之间互为友元
引用是可以理解为一个指针常量
可以改内容不可以改名字
我们可以用const修饰引用,既不可以该指针地址,也不可以改值
传指针才多大,当你要传的东西,大于指针地址的大小,为了速度呢前提是你不更改你传的东西,可以使用常量引用作为传值,若果要修改,就不要加常量修饰
注意了,返回引用本质是上返回指针,别啥玩意都返回引用,返回个野指针空指针啥的都是非法操作
传递者无许知道接受者是以引用(reference)的形式接受
标准库不是圣经,圣经还有错的呢,不是完美无缺的
构造函数的特殊语法初始化列表
相同class的各个objects互为友元
一个好的C++代码习惯:
总结:内联函数最佳,const能加就加,引用能用就用,类中变量数据最好放私有区域 用构造函数的特殊语法初始化列表
相当优雅
类的匿名对象可以用作temp object(临时对象) ,一般用在生命周期比较短的作用域
1 | return int( (int) char( 'a')); |
拷贝构造编译器默认有给。
但是遇到以下情况:就不能用默认的:
类带指针成员
自定义一个string
1 | class String |
函数实现
1 |
|
函数调用
1 | String s1(); |
注意了有拷贝构造,VS的编译器就不给你生成别的默认的构造函数了(你就自己用你自己设定的吧!哼
啥事栈(stack)?啥事堆(heap)啥事作用域(scope)?
若不知道,回炉重造
栈:
存在于某作用域(scope)的一块内存空间。调用一个函数,函数本身会形成一个栈来方式所接还送肚饿参数和返回地址。
堆:
系统分配的(具体怎么分配问你操作系统)提供的一块全局的内存空间
程序可以动态分配区块,你得手动释放这块内存,才会死,否则只能就交给操作系统处理,具体怎么处理,还是得问问操作系统。
static静态修饰的玩意在全局区,直到程序结束
new 不是函数,实际上是一个操作符
而malloc才是一个函数
new的底层调用了malloc,然后调用构造函数ctor
delete同理
底层原理:先调用析构函数dtor 后调用free
VC编译器c的动态内存分配
注意是32位的操作系统下。
分配的内存块(in VC),必须是16的倍数,除了本身的数据以外,还有两个4字节的头与尾cokie 值为总内存块的大小转16进制最后一位为1
1代表着,系统给出内存。0就没有给出,可以理解为一个标志
注意,分配的若是数组,将会分配的内存块中会有一个整数(4字节),值是数组的长度
调用delete时 也会先调用数组的长度次数的析构函数,再释放free内存
在使用NEW和 delete 的操作需要特别确认,不会出现误操作
namespace的使用
慎用unsing namespace std;
以防造成命名空间混乱
当然偷懒还是可以使用,指定特定的使用
using std::cout
OOP面向对象编程
基于对象的编程,C++与C的不同。
- Inheritance
- Composition
- Delegation
Composition复合
实际上这是最常见最简单的,一个类作为容器包含着其他的类
通俗的例子,在C 中,结构体中的成员是结构体,但是,严格上来讲,还是不一样的,当然先这么理解没问题
Adapter设计模式中可以见到
在复合的关系构造与析构,实际上可以理解为包装礼盒
里面的东西打包,再打包,这就是构造的顺序
拆礼物就不用说的,先拆外壳,在拆里头的东西,这就是析构的顺序
这是稳定的。
Delegation委托
Composition by reference
复合的引用版
类中掌握着一个指向其他类的指针,所以,也被称为Composition by reference
1 | class stringRep; |
需要注意这两个类的生命周期了,不同步的,是异步的,pimpl(handle/Body)
相当灵活的是,这个指针是可以指向其他的类的
Inheritance继承
在C中只有一种继承方式,
struct 的 pubilc
而C++有三种继承(分三种的原因,其实就是类与结构体的区别)
不同的继承
基类子类的成员之间的关系也不同。
有这么一种生物上的解释
子类中含有父类的基因,可以这么理解
子类对象的构造与析构一样是,由内而外与由外而内(打包礼物和拆礼物)
子类中定义的成员函数,要是与基类名字相等,这里就需要用到虚函数了,这就是继承中最核心的部分
- non-virtual
- virtual
- pure virtual
pure virtual 纯虚函数,子类必须重新定义的(重写)的函数
继承与复合的构造与析构
子类继承基类同时复合其他类的析构顺序,代码测试结果如下
1
2
3
4
5
6基类构造
其他类构造
子类构造
子类析构
其他类析构
基类析构可以发现,构造顺序是从基类开始
然后是复合类,才到子类
继承的基类优先级最高
在内存分布中是在第一位相对于子类中其他复合类而言
委托与继承的结合实际应用中是使用的最多的
比如说一个数据多种不同的表现方式
面型对象中应用的设计模式
Composite
应用实际:文件夹结构系统
文件夹中有文件和文件夹。
对未来子类的继承CLASS的规划
Prototype模式
图解
-私有
保护
下划线 静态
变量名:变量类型
函数名(函数参数)