我承认我是来领1024勋章的。时间有限,把最近看的C++基础发上来,算是自己默默走过的印迹。我承认我是野生程序员,非计算机专业,但一直在编码编码编码,并没有一个靠谱的大牛来带(当然这是我一直的梦想吧?呵呵~),全靠自己一步一步的走,一点一点的摸索。永远觉得自己缺血,所以也永远一直在持续充电。并不知道在这条路上还能走多久,甚至慢慢的连通向哪儿都不知道了,一路风尘,且行且珍惜吧。–2018年10月24日
这份教程是偶然遇到的,都简单的内容,但,貌似都又是需要加强的部分。野生程序员缺的并不是招式,是最基础的内功!有缘人跟着我用不到一个月的时间来练内功吧~有缘江湖再见。–2020年3月30日更新
在这里c++基础内容基本都有,人生苦短,精力有限,以后会把都c++的学习限制在这篇文章范围内,不再进行扩展。–2020年3月31日更新
估计会有人不赞同我写的内容,不要紧不要紧,笔记而已,不必认真。这个版本先就这样吧,后面有时间再补充。好歹不是一个大坑了。–2020年4月2日
总体框架图如下,分9个模块:基础C,高级C,基础C++,面向对象C++,高级C++,STL,设计模式,数据结构,基础算法。
基础C
- 内存:数据类型;堆栈;
- 指针:间接赋值;*p;一级指针;二级指针;形参;实参;内存首地址;
- 字符串:初始化;sizeof;strlen;copy;strstr;反转;递归;const;
- 二级指针:指针的指针;多级指针
- 多维数组:数组首元素的地址;数组地址;数组类型;指针数组;数组指针;
高级C
- 结构体:内存对齐;
- 文件操作:stream;文件缓冲区;输入输出流;文件指针FILE*;
- 链表:非顺序存储;动态链表;静态链表;带头链表,不带头链表;单向链表;双向链表;循环链表;
- 函数指针:指针函数;函数指针;回调函数;
- 预处理:文件包含;宏定义;条件编译;预定义宏;#include< >#include“ ”;
- 动态链接库:DLL;隐式链接方式;显式链接方式;
基础C++(扩展C)
- C Language Enhancements:namespace 命名空间;struct;bool;三目运算符;const:const常量由编译器处理,提供类型检查和作用域检查;#define由预处理器处理,单纯的文本替换;枚举;
#include <iostream>
using namespace std;//std是C++的标准命名空间
cout<<3.14 <<endl;
using namespace name;//使用整个命名空间
using name::variable;//使用命名空间中的变量
::variable;//使用默认命名空间中的变量
- C Language Extension:引用;inline内联函数;默认参数和占位参数;函数重载;
面向对象C++(伪装成类的C)
- Class and Object:封装;访问控制;成员变量、成员函数、输入输出流;对象的构造和析构;拷贝构造函数;深拷贝和浅拷贝;静态成员;友元;重载运算符;
- 继承和派生:类与类之间的关系;public,protected,private;构造和析构;多继承;虚继承;
- 多态:虚函数,虚析构函数,重载,重写,重定义;
高级C++
- 模板:泛型,Templates,函数模板,类模板;
- 类型转换:static_cast,dynamic_cast,const_cast,reinterpret_cast;
- 异常:throw;try……catch……;
- 输入输出流:C,printf,scanf,;CPP,iostream, ;
STL
STL(Standard Template Library,标准模板库)来源于惠普实验室。有13个头文件组成。分为三部分:容器(container); 算法(algorithm) ;迭代器(iterator)。
- 容器
string;vector;deque;queue;stack;list;set/multiset;map/multiset
说当我们给容器中插入元素的时候,容器内部实施了拷贝动作,将我们要插入的元素再另行拷贝一份放入到容器中,而不是将原数据元素直接放进容器中,也就是说我们提供的元素必须能够被拷贝。
- vector 的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描述。
- deque 的使用场景:比如排队购票系统,对排队者的存储可以采用 deque,支持头端的快速移除,尾端的快速添加。如果采用 vector,则头端移除时,会移动大量的数据,速度慢。
- list 的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。
- set 的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
- map 的使用场景:比如按 ID 号存储十万个用户,想要快速要通过 ID 查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是 vector 容器,最坏的情况下可能要遍历完整个容器才能找到该用户。
- 算法
STL算法分类质变算法和非质变算法,质变算法指运算过程中会改变区间内的元素内容,如copy\swap\replace\fill\remove\sort,非质变算法反之,如find\count\for_each\max\min。
设计模式
武功修炼=软件开发
招式:编程语言;开发工具;开发技术;框架技术
内功:数据结构;算法;设计模式;重构;软件工程
设计模式之父Christopher Alexander,这货是学建筑的。“设计模式是在特定环境下人们解决某类重复出现问题的一套成功或有效的解决方案。”
Software Patterns
设计模式目前种类: GoF (Gang of Four)共提出23个设计模式+ “简单工厂模式” = 24 种。
设计模式的基础是:多态
面向对象设计原则的目的: 高内聚,低耦合
- 面向对象设计原则:开闭原则;迪米特法则;合成复用原则;依赖倒转原则
- 创建型(Creational)模式:如何创建对象;
- Simple Factory Method:
工厂(Factory)角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
抽象产品(AbstractProduct)角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色:简单工厂模式所创建的具体实例对象。 - Factory Method:
抽象工厂(Abstract Factory)角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。
工厂(Concrete Factory)角色:具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
抽象产品(Abstract Product)角色:工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色:工厂方法模式所创建的具体实例对象。 - Abstract Factory Method:
工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个“产品族,由同一个工厂来统一生产,这就是我们本文将要学习的抽象工厂模式的基本思想。
抽象工厂(Abstract Factory)角色:它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
具体工厂(Concrete Factory)角色:它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
抽象产品(Abstract Product)角色:它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
具体产品(Concrete Product)角色:它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。 - Singleton Method:如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
- 结构型(Structural )模式:如何实现类或对象的组合;
- 代理模式:
subject(抽象主题角色):真实主题与代理主题的共同接口。
Real Subject(真实主题角色):定义了代理角色所代表的真实对象。
Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。 - 装饰模式:
Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。 - 外观Facade模式:
Façade(外观角色):为调用方, 定义简单的调用接口。
SubSystem(子系统角色):功能提供者。指提供功能的类群(模块或子系统) 。 - 适配器Adapter模式:
Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对 Adaptee 和 Target 进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承 Target 并关联一个 Adaptee 对象使二者产生联系。
Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
- 行为型(Behavioral)模式: 用来对类或对象怎样交互和怎样分配职责进行描述。
- 模板方法模式:
AbstractClass(抽象类):在抽象类中定义了一系列基本操作,这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
ConcreateClass(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。 - 命令模式:
Command(抽象命令类):抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的 execute()等方法,通过这些方法可以调用请求接收者的相关操作。
ConcreteCommand(具体命令类):具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现 execute()方法时,将调用接收者对象的相关操作(Action)。
Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的 execute()方法,从而实现间接调用请求接收者的相关操作。
Receiver(接收者):接收者执行与请求相关的操作,它具体实现对请求的业务处理。 - 策略模式:
Context(环境类):环境类是使用算法的角色,它在解决某个问题(即实现某个方法)时可以采用多种策略。在环境类中维持一个对抽象策略类的引用实例,用于定义所采用的策略。
Strategy(抽象策略类):它为所支持的算法声明了抽象方法,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法。
ConcreteStrategy(具体策略类):它实现了在抽象策略类中声明的算法,在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。 - 观察者模式:
Subject(被观察者或目标,抽象主题):被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject 需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject(具体被观察者或目标,具体主题):被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者):接口或抽象类。当 Subject 的状态发生变化时,Observer对象将通过一个 callback 函数得到通知。
ConcreteObserver(具体观察者):观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
数据结构
语言无关性
设计模式:可扩展性、灵活性、可复用性,
数据结构:基础单元之间的关系,不研究复杂的算法。
数据结构涉及到的专有名词:数据,数据元素,数据项,数据对象,
- 线性表代表数据元素的有限序列。线性表通常的操作方式有:创建、销毁、清空、插入、删除、获取、长度。
顺序存储,链式存储
单链表,循环链表,双向链表
//初始化链表
LinkList* InitLinkList();
//销毁链表
void DestroyLinkList(LinkList* list);
//链表中在指定位置插入结点
int InsertLinkList(LinkList* list, int pos, ListNode* node);
//删除指定位置结点
int DeleteLinkList(LinkList* list, int pos);
//链表是否为空
int IsEmptyLinkList(LinkList* list);
//返回链表长度
int GetLengthLinkList(LinkList* list);
//清空链表
void ClearLinkList(LinkList* list);
//打印链表结点
void PrintLinkList(LinkList* list, PrintLinkListData print);
//获得指定位置的结点
ListNode* GetNodeLinkList(LinkList* list, int pos);
- 受限线性表:stack;queue;
- 树和二叉树:树、二叉树、满二叉树、完全二叉树
左孩子右兄弟
牢记一种约定,对每个结点的查看都是“先左后右” 。
先 (根)序遍历 中 (根)序遍历 后(根)序遍历 - C++模板类与数据结构
所有容器提供的都是值(value)语意,而非引用(reference)语意。容器执行插入元素的操作时,内部实施拷贝动作。所以 STL 容器内存储的元素必须能够被拷贝(必须提供拷贝构造函数)。
C++模板是容器的概念。STL中构建了各种容器,C++的标准模板库,名副其实
链式存储:链表类,栈类,队列类
顺序存储:链表类,栈类,队列类
基础算法
算法:特定问题求解步骤的描述,是独立存在的一种解决问题的方法和思想。、
算法涉及到的专有名词:
- 输入,输出,有穷性,确定性,可行性;
- 事后统计法,事前分析估算;
- 大O表示法;
- 空间复杂度,时间复杂度。
- 排序算法
编程工具:ubuntu下的qt4~
参考文献
- 《C语言程序设计 第三版》 谭浩强