(1) C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。C++ 是由 Bjarne Stroustrup 于 1979 年在新泽西州美利山贝尔实验室开始设计开发的。 (2) 面向对象程序设计:封装、抽象、继承、多态。 (3) 标准库:核心语言:提供了所有构件块、包括变量、数据类型和常量。C++标准库:提供了大量的函数。标准模板库(STL):提供了大量的方法,用于操作数据结构。 (4) ANSI标准:可在Mac、UNIX、Windows、Alpha上编译。
(1) 文本编辑器:windows:Notepad,visual studio。UNIX:vim/vi,vscode、cloudstudio。Mac:Xcode。 (2) G++编译:g++ runoob1.cpp runoob2.cpp -o runoob,g++ -g -Wall -std=c++11 main.cpp (3) G++常用命令选项:
(1) 对象、类、方法、即时变量 (2) 标识符:以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。 (3) 关键字
单行注释://,多行注释:/* */,也可以:#if 0 ……#endif。
(1)基本内置类型 可以加入signed、unsigned、long、short。 (2)typedef type newname; (3)enum 枚举名{标识符[=整形常数],标志符[=整形常数]} 枚举变量;
(2)变量声明:当使用多个文件且只在其中一个文件中定义变量时,需要声明,使用extern type name; (3)左值和右值:
(1) 局部变量: 在函数或一个代码块内部声明的变量,形式参数:在函数参数的定义中声明的变量,全局变量:在所有函数外部声明的变量。 (2) 局部变量需要自己初始化,全局变量系统自动初始化,
常量是固定值,在程序执行期间不会改变。 (1) 整数常量:前缀,八进制:0,十六进制:0x或0X。后缀,U:无符号整型,L:长整数。 (2) 浮点常量:浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。 (3) 布尔常量:true值代表真,false值代表假。 (4) 字符常量:在单引号中,L开头(L’x’)表示宽字符常量,存储为wchar_t类型,否则为窄字符常量,存储为char类型。转义序列: (5) 字符串常量:双引号“”中。 (6) 定义常量:#define预处理器,const关键字。区别:#define只是一个常数,不带类型,预处理阶段起作用,简单的字符串替换,const是一个变量,有类型,编译运行时起作用。
(1) 数据类型修饰符:signed、unsigned、long、short。 (2) 类型限定符:
(1)auto存储类:自 C++ 11 以来,auto 关键字用于两种情况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。C++98标准中auto关键字用于自动变量的声明,但由于使用极少且多余,在C++11中已删除这一用法。 (2)register存储类:寄存器只用于需要快速访问的变量。register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)。 (3)static存储类:static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。 (4)extern存储类:extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 ‘extern’ 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。 (5)mutable存储类:mutable成员可以通过const成员函数修改。 (6)thread_local存储类:使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。thread_local 说明符可以与 static 或 extern 合并。可以将 thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。
(1)算术运算符: (3) 关系运算符: (4) 逻辑运算符: (5) 位运算:&、|、^ (6) 赋值运算符: (7) 杂项运算符: (8)运算符优先级:
(1) 循环类型: (2)循环控制语句:
?:表达式1:表达式2。
(1) 定义函数:return_type function_name(parameter list){} (2) 函数声明:return_type function_name(parameter list); (3) 函数调用: (4) 函数参数:传值调用、指针调用、引用调用。 (5) 参数的默认值:如果没有传递值,则为默认值。 (6) lambda函数与表达式:有返回值的形式:capture->return-type{body},没有返回值的形式:capture{body}。
(1) 数学运算:cmath库。
(1) 声明数组:type arrayName[arraySize]; (2) 初始化数组:type arrayName[arraySize]={}; (3) 访问数组元素:arrayName[index]; (4) 数组详解:
(1) 风格字符串:char greeting[6] = {‘h’,’e’,’l’,’l’,’o’,’\0’}或者char greeting[]=’hello’。 (2) 函数: (3) string类。
指针是一个变量,其值为另一个变量的地址,内存位置的直接地址。 (1)指针变量声明:type var_name; (2)指针的使用:定义一个指针变量()、把变量地址赋值给指针变量(&)、访问指针变量中可用地址的值。 (3)指针:
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。 (1)引用vs指针的不同:a、不存在空引用。引用必须连接到一块合法的内存。B、一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。C、引用必须在创建时被初始化。指针可以在任何时间被初始化。 (2)创建引用:type& newname = oldname;
引用头文件。 (1) 四个类型:clock_t、time_t、size_t、tm。clock_t、time_t、size_t能够把系统时间和日期表示为某种整数。 (2)重要函数:
(1) I/O库头文件 (2) 标准输出流cout:“<<”分割,endl换行 (3) 标准输入流cin:“>>”分割。 (4) 标准日志流clog:“<<”预定义的对象 clog 是 iostream 类的一个实例。clog 对象附属到标准错误设备,通常也是显示屏,但是 clog 对象是缓冲的。这意味着每个流插入到 clog 都会先存储在缓冲在,直到缓冲填满或者缓冲区刷新时才会输出。 (5) 编程时,通常使用cerr流来显示错误信息,而其他的日志消息使用clog流输出。
(1)定义结构: (2)访问结构成员:成员访问运算符(.)。 (3)结构作为函数参数:struct typename parameter。 (4)指向结构的指针:struct typename *object_name,访问成员用(->)。 (5)typedef关键字:别名,typedef struct typename{}
(1) 类的定义:class 类名{成员}。 (2) 对象的定义:类名 对象名。 (3) 访问数据成员:成员访问运算符(.)。 (4) 类成员函数:成员函数外部定义:返回类型 类名::类成员函数(形式参数)。 调用类成员函数:对象名.类成员函数(实参)。 (5)类访问修饰符:private、public、protected。默认为private。Public成员:外部可以访问。Private:外部不可访问,甚至不能查看。Protected:与private相似,与private不同在于成员在派生类中可以被访问。Public、private、protected三种继承: (5) 构造函数和析构函数: 构造函数:类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。 带参数的构造函数:默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数。这样在创建对象时就会给对象赋初始值。 析构函数:类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。 (6)拷贝构造函数: (7)友元函数: 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。 友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend。 因为友元函数没有this指针,则参数要有三种情况: 1、要访问非static成员时,需要对象做参数;2、要访问static成员或全局变量时,则不需要对象做参数;3、如果做参数的对象是全局对象,则不需要对象做参数. (8)内联函数: (9)this指针:在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。 (10)指向类的指针:一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。 (11)类的静态成员:我们可以使用 static 关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。 静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化。 静态成员函数:
(1)基类和派生类:class derived-class: access-specifier base-class (2)访问控制和继承: (3)继承类型: (4)多继承:
(1)函数重载:在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。不能仅通过返回类型的不同来重载函数。 (2)运算符重载:加法的重载:Box operator+(const Box&);box为类对象。 (3)可重载的运算符: (4)不可重载运算符:
作用:多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。 (1)虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。 我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。 (2)纯虚函数:可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。定义方式:virtual type func()=0;
(1)访问标签强制抽象:在 C++ 中,我们使用访问标签来定义类的抽象接口。一个类可以包含零个或多个访问标签: • 使用公共标签定义的成员都可以访问该程序的所有部分。一个类型的数据抽象视图是由它的公共成员来定义的。 • 使用私有标签定义的成员无法访问到使用类的代码。私有部分对使用类型的代码隐藏了实现细节。 访问标签出现的频率没有限制。每个访问标签指定了紧随其后的成员定义的访问级别。指定的访问级别会一直有效,直到遇到下一个访问标签或者遇到类主体的关闭右括号为止。 (2)数据抽象的好处: 数据抽象有两个重要的优势: • 类的内部受到保护,不会因无意的用户级错误导致对象状态受损。 • 类实现可能随着时间的推移而发生变化,以便应对不断变化的需求,或者应对那些要求不改变用户级代码的错误报告。 如果只在类的私有部分定义数据成员,编写该类的作者就可以随意更改数据。如果实现发生改变,则只需要检查类的代码,看看这个改变会导致哪些影响。如果数据是公有的,则任何直接访问旧表示形式的数据成员的函数都可能受到影响。
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
(1) 打开文件:open() 函数是 fstream、ifstream 和 ofstream 对象的一个成员。void open(const char *filename, ios::openmode mode);第一个参数指定要打开的文件的名称和位置。第二个参数是模式: (2) 关闭文件:void close(); (3) 写入文件:<< (4) 读取文件:>> (5)文件位置:seekg 和 seekp 的参数通常是一个长整型。第二个参数可以用于指定查找方向。查找方向可以是 ios::beg(默认的,从流的开头开始定位),也可以是 ios::cur(从流的当前位置开始定位),也可以是 ios::end(从流的末尾开始定位)。
throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。 catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常。 try: try 块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个 catch 块。 (1) 抛出异常:throw (2) 捕获异常:try{保护代码}catch(exceptionname e){处理异常} (3) 异常:
栈:在函数内部声明的所有变量都将占用栈内存。 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。 (1)New和delete运算符: pvalue = new data-type delete pvalue (2)数组的动态内存分配: pvalue = new char[20]; delete [] pvalue;
解决多个库存在相同命名的函数。 (1) 定义命名空间:namespace namespace_name{声明代码} (2) 调用命名空间:namespace_name::func,using namespace namespace_name。
(1)函数模板: template ret-type func-name(parameter list) { // 函数的主体 } (2)类模板:template class class-name {…}
(1)#define预处理器:#define macro-name replacement-text (2)参数宏:#define MIN(a,b) (a<b ? a : b) (3)条件编译:if或ifndef或ifdef endif。 (4)#和##运算符:# 和 ## 预处理运算符在 C++ 和 ANSI/ISO C 中都是可用的。# 运算符会把 replacement-text 令牌转换为用引号引起来的字符串。## 运算符用于连接两个令牌。 (5)预定义宏:
基于进程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行。 (1)创建线程:#include <pthread.h> pthread_create (thread, attr, start_routine, arg) (2)终止线程: