C++知识点整理总结:
目录
一. C++(I)重点知识:
二. C++(II)重点知识:
C++书写标准:
- 数据放在private中
- 参数尽量用引用来传,需不需要const,看情况。
- 返回值尽量用引用来传
- 在类的本体中,函数应该加const的要加。
- 构造函数中的参数初始化列表要尽量用。
一.C++(I)重点知识:
主要介绍了两种class类型:1)class中不带指针成员 2)class中包含指针成员
*包含头文件的两种方法#include<>和#include””;
如果是自己写的头文件,使用#include””包含, 如果包含的是C++标准库,使用#include<>来包含。
头文件中使用防卫式声明:
建议:为了不必要的麻烦,最好在每个头文件上加上这样的防卫式声明。即使现在你只有一个cpp使用该头文件,万一之后再有别的cpp使用该头文件嘞。
PS:防卫式声明一般这样写:__(2个下划线,不是1个)+头文件名的大写(不包括.h)+__(2个下划线,不是1个),例如头文件为head.h时,就使用__HEAD__,这是为了防止重复。
目录
一. C++(I)重点知识:
1) class中不带指针成员
2) class中包含指针成员
1. Prototype设计模式:
2. 委托+继承关系下的Composite设计模式应用于文件系统开发的原理
3. 委托+继承关系下的observer设计模式的应用和原理
4. 继承+复合关系下的构造与析构函数调用
5. 虚函数和TemplateMethod模式的原理和应用重点
6.复合关系和Adapter模式以及复合关系下的构造和析构函数的讲解
二. C++(II)重点知识:
1) class中不带指针成员
- 关于inline的用法:
Inline用于函数的声明,函数可以被声明为inline类型及内联类型, inline函数提高运行效率(inline只是对编译器的一种建议,简单函数会被inline,复杂函数不一定会被inline),建议将函数inline.
在class内完成定义的函数,编译器会自动对其进行inline 尝试。
在class外完成定义的函数,可以使用inline关键字对其进行inline尝试。
2.关于友元函数的使用:
面向对象三大特性:封装,继承,多态。友元函数可以说是在保持封装性的情况下,提供了其他对象对另一个对象的操作方式(两个对象可以属于同一class,也可以不属于同一个class);同一class的不同对象之间是友元关系。
3.常量const的使用:
Const 修饰对象,若函数体内,不会对传入对象进行修改,则函数形参前加const,表示此对象在函数运行过程中不会被改变。
Const修饰函数, 即在函数名()之后加const修饰,可以保证函数在之后的运行过程中可以正确运行。可以使用以下例子来说明:
函数名( )之后加const,意味函数体内不会对成员数据进行任何更改操作。
之后无论是使用complex c1(2,1) 还是 const complex c1(2,1)来创建对象都可以;但是,如果不加const,使用 const complex c1(2,1)创建对象后,cout<<c1.real( )会报错。
4.关于构造函数的使用:
合理运用初始化列表可以有效提高运行效率。
构造函数的执行过程:先执行初始化列表,后执行函数体中的内容。
构造函数重载注意事项:
5.关于运算符重载:
1) return by value 还是 return by referrence??
若在函数内部没有创建临时对象,则尽量使用引用类型对返回值进行接收; 若在函数内部创建临时,则使用value对返回值进行接收.
使用reference接收的好处:
2) 临时对象:
再一个函数中,通过调用构造函数生成临时的一个对象,用来存储新生成的数据,当函数执行结束后,临时对象将会被编译器清除,可以通过返回value的方式,将临时对象中的数据返回。
3) 运算符重载(+,+=,<<)
重载<<, ostream& operator<<( ostream& os,const String str ) ,需要将重载函数写成全局函数。
2) class中包含指针成员
1.array New一定要搭配array Delete 使用:
例如:
如图: new String[3]意味创建了包含3个string类型对象的数组,在创建过程中会调用3次String类型的构造函数; 如果使用delelte p来释放p指针,则只会调用一次析构函数,释放p所指向的数组空间的第一个string对象, 但是数组空间中其余2个string类型对象中包含指针数据,指针数据所指向的内存空间并不会被释放掉,造成内存泄漏; 因此必须使用delelte [] p。array New一定要搭配array Delete使用。
2.namespace的使用:
3.stack和heap以及new和delete的使用和原理
- static的使用:
将class中的数据成员设置为static类型,或者将函数成员设置为static类型。设置为static的数据成员和函数成员,在内存中单独存在,static函数成员只能处理static数据成员,static函数中不包含this指针。
调用static函数的方式:
(1)通过object调用
(2)通过class name调用
1.单例模式:(singleton)
单例模式:确保一个类只有一个实例,并提供一个全局访问点。
例子:构造函数放在private域中
在此例子中只需要一个A的对象,可以使用单例模式来完成。
此例子中:
A的构造函数写在了private中,成员函数getinstance()用来创建一个A的静态对象a,并返回a对象的引用。
应用:单例模式可以用来做初始化数据库的连接操作,线程池,缓存,日志对象,显卡等设备的驱动程序。
经典的单例模式实现(java)(延迟实例化):
Public class Singleton{
Private static Singleton uniqueInstance;
//这里是其他的有用实例化变量
Private Singleton( ) { } //私有的构造函数
Public static Singleton getInstance( )
{
If(uniqueInstance == null)
{
uniqueInstance= new Singleton( );
}
Return uniqueInstance;
}
//这里是其他的有用方法
}
以上情况注意***在使用单例模式时,需要考虑多线程并发导致生成多个实例的情况。
处理多线程的方法:
1.将getInstance()变成同步(synchronized)方法, 若此段程序使用频繁,此方法会造成程序效率的大幅下降。
经典的单例模式实现(java)(延迟实例化):
Public class Singleton{
Private static Singleton uniqueInstance;
//这里是其他的有用实例化变量
Private Singleton( ) { } //私有的构造函数
Public static synchronized Singleton getInstance( )
{
If(uniqueInstance == null)
{
uniqueInstance= new Singleton( );
}
return uniqueInstance;
}
//这里是其他的有用方法
}
2.使用”双重检查加锁”,在getInstance()中减少使用同步。保证程序的性能。(最佳方法)
Public class Singleton{
Private Volatile static Singleton uniqueInstance;
//这里是其他的有用实例化变量
Private Singleton( ) { } //私有的构造函数
Public static Singleton getInstance( )
{
If(uniqueInstance == null)
{
synchronized (Singleton.class)
{
If(uniqueInstance == null)
{
uniqueInstance= new Singleton( );
}
}
}
return uniqueInstance;
}
//这里是其他的有用方法
}
使用”急切”创建实例,而不是使用延迟实例化的做法
经典的单例模式实现(java)(急切实例化):
Public class Singleton{
Private static Singleton uniqueInstance = new Singleton( );
//这里是其他的有用实例化变量
Private Singleton( ) { } //私有的构造函数
Public static Singleton getInstance( )
{
return uniqueInstance;
}
//这里是其他的有用方法
}
- cout函数的原理说明:
- 模板和函数模板:
- 浅拷贝和深拷贝:
class中包含指针数据成员,需要定义一下三种函数:
BIG Three函数:1.拷贝构造函数 2.拷贝赋值函数 3.析构函数
浅拷贝:
c++中,提供的对象之间的赋值是浅拷贝,例如:a=b; 将对象b赋值给对象a, 只是将a和b对象中的指针指向同一地址,这样会造成内存泄露;同时也会带来不确定性的危险,例如:在后续操作中,改变a或b中的某一指针所指地址中的数据,相当于a和b同时改变。
深拷贝:
通过拷贝构造函数不改变a和b对象中指针的地址,而将所指地址中的数据改为相同。
深拷贝两种方法:
1.拷贝构造函数:利用构造函数来进行对象的拷贝,例如:
String s1("Hello");
String s2(s1); //调用所属class的拷贝构造函数
2.拷贝赋值函数:利用运算符重载来进行对象的拷贝(赋值), 例如:
String s1("Hello");
String s2;
s2 = s1; // 调用class中operator成员函数
3.析构函数:在对象的生命周期结束时,被调用,用来将对象中的指针所指地址进行释放。
9.参数传递:pass by value vs pass by reference(to const)
1.使用value传递,可能因为数据的大小影响运行效率。例如:char数据是1个字节,指针是4个字节,”引用”本质上是指针的封装,但是速度比指针更快。
2.使用引用传递,速度更快,并且和指针传递效果一样,在函数内对可以对引用的数据进行修改。
3.上图中,complex& operator += (const complex&); 其中const表明:通过引用传递到函数体内的数据不能在函数体内进行修改。
返回值类型尽量使用引用。
面向对象编程重中之重(继承、复合、委托)
复合关系:及在一个类的数据成员中包含包含其他类的对象。
继承关系:及子类继承父类
委托关系:及在一个类的数据成员中包含包含其他类的指针。
- Prototype设计模式:
- 委托+继承关系下的Composite设计模式应用于文件系统开发的原理
- 委托+继承关系下的observer设计模式的应用和原理
- 继承+复合关系下的构造与析构函数调用
- 虚函数和TemplateMethod模式的原理和应用重点
6.复合关系和Adapter模式以及复合关系下的构造和析构函数的讲解
复合关系下,构造函数是先调用内部复合的构造函数,然后再执行自己的构造函数。析构函数是先执行自己的析构函数,再执行内部复合的析构函数。
二.C++(II)重点知识:
- 转换函数conversion function
- Pointer-like-class智能指针
Pointer-like-class智能指针: 就是像指针的class, 该类所创建的对象,拥有普通指针所拥有的功能,此外还可以根据自己的需要对其进行扩展。
- pointer-like-class智能指针-迭代器
- function-like-class仿函数
- class template 和 function template 和 menber template
- 模板特化和模板偏特化
- 模板模板参数
- reference的本质原理理解(重点)
9.复合继承关系下的构造和析构
复合关系下,构造函数是先调用内部复合的构造函数,然后再执行自己的构造函数。析构函数是先执行自己的析构函数,再执行内部复合的析构函数。
10.多态与虚函数与虚机制与虚指针的本质理解和关系
如果一个类中包含虚函数,则再内存分配中,会为该类的对象分配一个虚指针vptr,不论class中有多少个虚函数,对象中都只有一个虚指针; 虚指针指向虚表vtbl虚表中存有对象所包含虚函数的地址; 虚机制:就是对象在调用虚函数的过程中,通过虚指针找到虚表,通过虚表中虚函数的地址找到相应的虚函数,进行调用的过程。 多态是靠虚机制来进行表现。
- 关于this指针的理解:
当对象调用所属类的函数成员时,会隐式的将对象的地址传入函数中,this就是指向这个对象的指针。
- 关于动态绑定的理解:
动态绑定是与虚机制有关的,
- 关于new, delete, operatorNew和operatorDelete的重载(难)可用来做内存池
装饰者模式(组合composition+委托delegation):
适用于的情景: 利用继承无法完全解决问题,类数量爆炸、设计死板,以及基类加入的新功能并不适用于所有的子类。
目标是:允许类容易扩展,在不修改现有代码的情况下,就可以搭配新的行为,及(对扩展开放,对修改关闭)
注意:在选择需要被扩展的代码部分时要小心。每个地方都采用开放-关闭原则,是一种浪费,也没必要,还会导致代码变得复杂且难以理解。
观察者模式