C++学习笔记(二)

2023-05-16

1.C++简介 (参考C++菜鸟教程)
C++是一种静态的编译式的通用的大小写敏感的不规则的编程语言,支持过程编程、对象编程和泛型编程。
C++综合了高级语言和低级语言的特点,是一种中级语言。它是C的一个超集,事实上,任何合法的C程序都是合法的C++程序。标准库:标准的C++由三个重要部分组成:核心语言,提供了所有构建块,包括变量、数据类型和常量等;C++标准库,提供了大量的函数,用于操作文件、字符串等;标准模板库STL,提供了大量的方法用于操作数据结构等。
学习C++关键是要理解概念,而不是过于深究语言的技术细节,目的是成为一个更好的程序员,为了能更有效地设计和是实现新系统。
2.C++基本语法
C++可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。对象:具有状态和行为,状态比如颜色、名称等,行为比如叫、摇动等,对象数类的实例。类:类可以定义为描述对象/行为的模板。方法:从基本上说,一个方法表示一种行为,一个类可以包含多个方法,可以在方法中写入逻辑、操作数据以及执行所有的动作。即使变量:每个对象都有其独特的即时变量,对象的状态时有这些即使变量的值创建的。
3.C++数据类型
操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么。C++常用的七种数据类型:bool[1 byte],char[1 byte],int[4 byte],float[4 byte],double[8 byte],void,wchar_t[2/4 byte]. 1byte=8 bit
枚举类型 enum是C++的一种派生数据类型,它是由用户自定义的若干枚举常量的集合。如果一个变量值只有几种可能的值,可以定义为枚举类型,枚举就是将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。默认情况下第一个名称的值为0,以此类推。一般形式为:
enum 枚举名{ 标识符,标识符,… } 枚举变量; 枚举变量的类型就是枚举名的类型。
4.C++变量类型
变量就是程序可操作的存储区的名称。C++中每个变量都有指定的类型,类型决定了变量存储的大小和布局,该范围的值都可以存储在内存中,运算符可应用与变量上。变量的类型基于数据的类型,C++ 也允许定义各种其他类型的变量,比如指针、数组、引用、数据结构、类等。
C++中变量的定义:变量的定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。变量的定义指定一个数据类型,包括该类型的一个或多个变量的列表,如:type variable_list;int i,k,l;表示编译器创建类型为int的名为i,k,l的变量。
C++中变量的声明:变量的声明向编译器保证变量以给定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能进一步编译。变量声明只在编译时有它的意义,在程序链接时编译器需要实际的变量声明。当您使用多个文件且只在其中一个文件中定义变量时(定义变量的文件在程序连接时是可用的),变量声明就显得非常有用。您可以使用 extern 关键字在任何地方声明一个变量。虽然您可以在 C++ 程序中多次声明一个变量,但变量只能在某个文件、函数或代码块中被定义一次。
左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
5.C++变量作用域
作用域是程序的一个区域,一般来说有三个地方可以定义变量:a,局部变量:在函数或一个代码块内部声明的变量;b.形式参数:在函数的定义中声明的变量;c.全局变量:在所有函数外部声明的变量。
局部变量:只能被函数内部或代码块内部的语句使用。全部变量:在所有函数外部定义的变量,通常在程序头部,全局变量的值在程序的整个生命周期都是有效的。全局变量可以别任何函数访问。局部变量被定义是系统不会对其初始化,全局变量定义时,系统会自动初始化。
6.C++常量
常量时固定值,在程序执行期间不会改变,它可以是任何的基本数据类型,在定义后不能修改。在C++中有两中简单的定义常量方式:#define预处理器或const关键字。#define identifier value, const type variable=value;
7.C++修饰符类型
C++允许在char、int、double 数据类型前放置修饰符,用于改变基本类型的含义,跟能满足各类情境的需求。数据类型的修饰符有:signed,unsigned,long,short;它们都可用于整型,signed和unsigned可用与字符型,long可用于双精度型。修饰符 signed 和 unsigned 也可以作为 long 或 short 修饰符的前缀。
8.C++存储类
存储类定义C++程序中变量/函数的范围和生命周期。这些说明符放置在它们所修饰的类型值之前。下面列出C++程序中可用的存储类:auto,register,static,extern,mutable,thread_local(C++11). 从 C++ 17 开始,auto 关键字不再是 C++ 存储类说明符,且 register 关键字被弃用。
Static存储类:指示编译器在程序的生命周期内保持局部变量的存在,不需要在每次它进入和离开作用域时进行创建和销毁,因此,使用static修饰局部变量可以在函数调用之间保持局部变量的值。Static修饰符上也可以应用与全部变量,当static修饰全局变量时,会使变量的作用域限制在声明它定位文件内。在 C++ 中,当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。
Extern存储类:用于提供一个全局变量的应用,全局变量会对所有的程序文件都是可见的,当使用 'extern' 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候。
9.C++运算符
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号,C++内置了丰富的运算符,并提供了以下类型的运算符:算术运算符,关系运算符,逻辑运算符,位运算符,赋值运算符,杂项运算符。
关系运算符:==    检查两个操作数的值是否相等,如果相等则条件为真;!=  检查两个操作数的值是否相等,如果不相等则条件为真;>,<,>=,<=.
逻辑运算符:&& 逻辑与运算符,两个操作数都非零,则为真。||逻辑或运算符,两个操作数中有任意一个非零,则条件为真;!逻辑非运算符,用来逆转操作数的逻辑状态,条件为真则逻辑非运算符将使其为假。
位运算符:位运算符作用于位,并逐位执行操作,&,|,^,~,<<,>>.
杂项运算符:“sizeof”返回变量的大小,“Condition?X:Y”条件运算符,为真为X,否则为Y。“逗号,”运算符会顺序执行一系列运算,整个逗号表达式的值以逗号分隔的列表中的最后一个表达式的值。“点和->”成员运算符用于引用类、结构和共同体的成员。Cast强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。指针运算符 “&” 返回变量的地址。例如 &a; 将给出变量的实际地址。指针运算符”*” 指向一个变量。例如,*var; 将指向变量 var。
C++中的位运算符优先级:运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。
10.C++循环:
循环语句允许多次执行一个语句或语句组。
循环类型:while: 当给定条件为真时,重复语句或语句组,它会在执行循环主体之前测试条件; for: 多次执行一个语句序列,简化管理循环变量的代码;do …while: 除了它是在循环主体结尾测试条件外,其他与 while 语句类似; 嵌套循环:可以在 while、for 或 do..while 循环内使用一个或多个循环。
对于for(类型名  类型 : 需要遍历的数组),是先创建了对象或者变量,然后遍历数组,将数组里的值一个个赋值给类型,类型:可以是变量或对象,类型名:比如String,int,自己建的User对象。遍历数组的一种方式。
循环控制语句:循环控制语句更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁。 break终止loop或switch语句,程序将继续接着loop 或 switch 的下一条语句。 continue:引起循环跳过主体的剩余部分,立即重新开始重新开始测试条件;goto语句,将控制转移到被标记的语句。
11.C++判断:
判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件位真时要执行的语句(必须)和条件为假时要执行的语句(可选的)。
判断语句:if,if … else, 嵌套if语句,switch语句,嵌套switch语句。
?:运算符可以用来代替if…else语句。
12.C++函数:
函数是一组一起执行一个任务的语句,每个程序都至少有一个函数,即main().
函数声明告诉编译器函数的名称、返回类型和参数,函数定义提供了函数的实际主体。定义函数一般形式为:return _type function_name (parameter list) {body of the function}, 函数由一个函数头和一个函数体组成,返回类型:可以返回一个值,也可以返回为空; 函数名字:函数名和参数列表一起构成函数签名。参数就像占位符,当函数被调用时,向函数传递一个值(实参),参数列表包括参数的类型、顺序、数量。函数主体包含一组定义函数执行任务的语句。
调用函数:创建函数时会定义函数做什么,然后通过调用函数来定义的任务。当程序调用函数时,程序控制权会转移个被调用的函数,被调用的函数执行已定义的任务,当函数的返回语句被执行时,或达到函数的结束括号时,会把程序控制权交换给主程序。调用函数参数列表可以省,用默认参数,但括号不能省。
函数参数:在定义函数时函数名后面括号中的变量名称称为形式参数,它就像函数内的其他局部变量一样,进入函数时被创建,推出时被销毁。当调用函数时,由三种向函数传递参数的方式:传值调用:把参数实际值赋给函数的形参;指针调用:把参数的地址赋值给形式参数,在函数内,该地址用于访问调用中要用到的实际参数,意味着修改形参会影响实际参数;引用调用:把参数的引用赋值个形式参数,在函数内,该引用用于访问调用要用到的实际参数,修改形参会影响实际参数。默认情况下,C++ 使用传值调用来传递参数。一般来说,这意味着函数内的代码不能改变用于调用函数的参数。
参数的默认值:定义一个参数时,可以为参数列表中后边的每一个参数指定默认值,调用时如果实参留空,则使用默认值。如果指定了值,则使用传递值。
Lambda函数与表达式:把函数看作对象,可以像对象一样使用,Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。Lambda 表达式具体形式如下:[capture](parameters)->return-type{body}, 没有返回值: [capture](parameters){body}. [capture]:捕捉列表。捕捉列表总是出现在 lambda 表达式的开始处。事实上,[] 是 lambda 引出符。编译器根据该引出符判断接下来的代码是否是 lambda 函数。捕捉列表能够捕捉上下文中的变量供 lambda 函数使用。(parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号 () 一起省略。->return_type:返回类型。用追踪返回类型形式声明函数的返回类型。出于方便,不需要返回值的时候也可以连同符号 -> 一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。{body}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
13.C++数字:
随机数:关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数
14.C++数组:
声明: type arrayName[arraySize];声明一个一维数组。type name[size1][size2]…[sizeN];
指向数组的指针:数组名是一个指向数组中第一个元素的常量指针,double balance[50]; double p*;p=balance;p为balance的第一元素的地址。使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4) 是一种访问 balance[4] 数据的合法方式。一旦您把第一个元素的地址存储在 p 中,您就可以使用 *p、*(p+1)、*(p+2) 等来访问数组元素。p是一个指向 double 型的指针,这意味着它可以存储一个 double 类型的变量。一旦有了 p 中的地址,*p 将给出存储在 p 中相应地址的值。
传递数组给函数:可以通过指定不带索引的数组名来传递一个指向数组的指针。C++ 传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址。如果您想要在函数中传递数组作为参数,必须以下面三种方式来声明函数形参:形参是一个指针,形参是一个已经定义的数组,形参是以个未定义大小的数组。
从函数返回数组,C++不允许返回一个完整的数组作为函数,但是可以通过指定不带索引的数组名来返回一个指向数组的指针。如果想要返回一个以维数组,必须声明一个返回指针的函数。C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。
15.C++字符串:
C风格: char greet[6]={‘H’,’e’,’l’,’o’,’\n’}; string类, string str1=’hello’,str2=’world’; str1+str2;str1.size().
16.C++ 指针??:
通过指针可以简化一些编程任务的执行,还有一些动态内存分配,没有指针是无法执行的。每一个变量都有一个内存位置,每个内存位置都定义了可使用”&”运算符访问的地址,表示了在内存中的一个地址。
指针是一个变量,其值是另一个变量的地址,即内存位置的直接地址,就像其他变量或常量一样,必须在使用指针存储其他变量地址之前对其进行声明。一般形式: type *var-name;使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针”&”、访问指针变量中可用地址的值”*”。这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。
指针的算术运算:指针是一个用数值表示的地址,可以对指针执行算术运算。四种算术运算:++、--、+、-。
指针和数组:指针和数组在很多情况下是可以互换的。可以通过使用指针的算术运算或数组索引来访问数组。可以用一个指向字符的指针数组来存储一个字符串列表。
指向指针的指针:指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。
传递指针给函数:只需要简单地声明函数参数为指针类型即可。
17.C++引用:
一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。引用和指针的三个不同:不存在空引用,必须链接到一块合法内存;一旦引用被初始化为一个对象,就不能被指向到另一个对象,指针可以在任何时候指向到另一个对象;引用必须在创建时被初始化,指针可以在任何时间被初始化。
18.C++基本的输入输出:
如果字节流是从设备(如键盘、磁盘驱动器、网络连接等)流向内存,这叫做输入操作。如果字节流是从内存流向设备(如显示屏、打印机、磁盘驱动器、网络连接等),这叫做输出操作。
<iostream>:定义了 cin、cout、cerr 和 clog 对象,分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。<iomanip>:该文件通过所谓的参数化的流操纵器(比如 setw 和 setprecision),来声明对执行标准化 I/O 有用的服务。<fstream>:该文件为用户控制的文件处理声明服务。
19.C++数据结构:
数组允许定义可存储相同类型数据项的变量,但是结构是 C++ 中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:struct type_name {member_type1 member_name1;member_type2 member_name2; …} object_names; type_name 是结构体类型的名称,member_type1 member_name1 是标准的变量定义. 使用成员访问运算符(.)访问结构的成员. 结构作为函数参数: 传参方式与其他类型的变量或指针类似。指向结构的指针: 方式与定义指向其他类型变量的指针相似, struct Books *struct_pointer;必须使用 “->”指针运算符指向该结构的指针访问结构的成员. (???)
20.类&对象:
类是C++的核心特性,用与指定对象的形式,它包含了数据表示法和用于处理数据的方法,类中的数据和方法称为类的成员。
C++类的定义:定义一个类本质上是定义一个数据类型的模板,定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。类的关键字class,后跟类的名称,类的主体包含{}中,类定义后必须跟着一个分号或一个声明列表。类中关键字public确定了类成员的访问属性,在类对象作用域内,公共成员在类的外部是可以访问的。类的对象的公共数据成员可以使用直接成员访问运算符 (.) 来访问。关键字private 或 protected私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问。
类的成员函数:指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。成员函数可以定义在类定义内部,或者单独使用范围解析运算符 “::”来定义。在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符。
类访问修饰符:数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。成员和类的默认访问修饰符是 private。protect成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
构造函数&析构函数:类的构造函数是一种特殊的函数,在创建一个新的对象时调用。类的析构函数也是一种特殊的函数,在删除所创建的对象时调用。构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。如果需要,构造函数也可以带有参数。这样在创建对象时就会给对象赋初始值。使用初始化列表来初始化字段,C::C( double a, double b, double c): X(a), Y(b), Z(c){};析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:通过使用另一个同类型的对象来初始化新创建的对象;复制对象把它作为参数传递给函数;复制对象,并从函数返回这个对象。
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend。
内联函数inline:引入内联函数的目的是为了解决程序中函数调用的效率问题,程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。这其实就是个空间代价换时间的i节省。所以内联函数一般都是1-5行的小函数。在使用内联函数时要留神:1)在内联函数内不允许使用循环语句和开关语句;2).内联函数的定义必须出现在内联函数第一次调用之前;3)类结构中所在的类说明内部定义的函数是内联函数,应该满足内联函数的定义。
this 指针:每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。友元函数没有 this 指针,因为友元不是类的成员。
指向类的指针:一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。
类的静态成员:使用 static 关键字来把类成员定义为静态的。当声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。静态成员在类的所有对象中是共享的,因此静态成员函数时类的成员静态成员函数,不能称为对象的的静态成员函数。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化
常量变量:必须通过构造函数参数列表进行初始化。引用变量:必须通过构造函数参数列表进行初始化。普通静态变量:要在类外通过"::"初始化。静态整型常量:可以直接在定义的时候初始化。静态非整型常量:不能直接在定义的时候初始化。要在类外通过"::"初始化。
21. C++继承
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。继承代表了 is a 关系。例如,哺乳动物是动物。
派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。一个派生类继承了所有的基类方法,但下列情况除外:基类的构造函数、析构函数和拷贝构造函数;基类的重载运算符;基类的友元函数。
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。通常使用 public 继承。
公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
多继承即一个子类可以有多个父类,它继承了多个父类的特性。
22. 重载运算符和重载函数
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
当调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
函数重载:在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
运算符重载:重定义或重载大部分 C++ 内置的运算符。这样能使用自定义类型的运算符。有些运算符可以重载有些不可以,详略。
23.C++多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。C++中多态的表现形式就是重载和虚函数。
24. 数据抽象
数据抽象指只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程技术。抽象把代码分离为接口和实现。所以在设计组件时,必须保持接口独立于实现,这样,如果改变底层实现,接口也将保持不变。这种情况下,不管任何程序使用接口,接口都不会受到影响,只需要将最新的实现重新编译即可。
25.数据封装
所有的C++程序都有以下两个基本要素:程序语句(代码)-函数,程序数据。封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
通常情况下,我们都会设置类成员状态为私有(private),除非我们真的需要将其暴露,这样才能保证良好的封装性。这通常应用于数据成员,但它同样适用于所有成员,包括虚函数。
26.接口(抽象类)
接口描述了类的行为和功能,而不需要完成类的特定实现。C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。
27. 文件和流
从文件读取流和向文件写入流需要用到 C++ 标准库 fstream,它定义了三个数据类型:ofstream: 表示输出文件流,用于创建文件并向文件写入信; ifstream: 表示输入文件流,用于从文件读取信息;fstream表示文件流,同时具有 ofstream 和 ifstream 两种功能,创建文件,向文件写入信息,从文件读取信息。C++ 中进行文件处理,必须在 C++ 源代码文件中包含头文件 <iostream> 和 <fstream>。
打开文件:在文件读取或写入信息之前必须先打开文件,ofstream 和 fstream 对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,则使用 ifstream 对象。open() 函数是 fstream、ifstream 和 ofstream 对象的一个成员。void open(const char *filename, ios::openmode mode); 第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。想要打开一个文件用于读写,可以使用下面的语法:ifstream  afile; afile.open("file.dat", ios::out | ios::in );关闭文件:afile.close();写入文件:使用流插入运算符( << )向文件写入信息。
28.异常处理
C++ 异常处理涉及到三个关键字:try、catch、throw。当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的,catch 关键字用于捕获异常,try 块中的代码标识将被激活的特定异常。                                                                
29.动态内存
了解动态内存在 C++ 中是如何工作的是成为一名合格的 C++ 程序员必不可少的。C++ 程序中的内存分为两个部分:
栈:在函数内部声明的所有变量都将占用栈内存。堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。很多时候,无法提前预知需要多少内存来存储某个定义变量中的特定信息,所需内存的大小需要在运行时才能确定。很多时候,您无法提前预知需要多少内存来存储某个定义变量中的特定信息,所需内存的大小需要在运行时才能确定。如果您不再需要动态分配的内存空间,可以使用 delete 运算符,删除之前由 new 运算符分配的内存。使用 new运算符为任意的数据类型动态分配内存的通用语法: new datatype;datatype可以是包括数组在内的任意内置的数据类型,也可以是包括类或结构在内的用户自定义的任何数据类型。
30.命名空间
本质上命名空间就是定义了一个范围,定义使用关键字 namespace,后跟命名空间的名称。调用带有命名空间的函数或变量,需要在前面加上命名空间的名称.
不连续的命名空间:命名空间可以定义在几个不同的部分中,因此命名空间是由几个单独定义的部分组成的。一个命名空间的各个组成部分可以分散在多个文件中。所以,如果命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称。
31.模板:
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。
C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。模板是一种对类型进行参数化的工具;通常有两种形式:函数模板和类模板;函数模板针对仅参数类型不同的函数;类模板针对仅数据成员和成员函数类型不同的类。使用模板的目的就是能够让程序员编写与类型无关的代码。
函数模板的格式:template <class type,class type,......> 返回类型 函数名(参数列表){函数体},<>括号中的参数叫模板形参,举例一个交换函数:template <class T> void swap(T& a, T& b){},调用这样的模板函数时类型T就会被被调用时的类型所代替。可以 swap(1,2),swap(1.2,1.3);在函数调用的参数中不能指定模板形参的类型,对函数模板的调用应使用实参推演来进行。(实参(argument):全称为"实际参数"是在调用时传递给函数的参数. 实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。形参(parameter):全称为"形式参数" 由于它不是实际存在变量,所以又称虚拟变量。是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数.在调用函数时,实参将赋值给形参。实参的个数、类型应与形参一一对应,实参必须要有确定的值。)
类模板的格式:template<class type,class type,…>   class 类名 { ... }; 一旦声明了类模板就可以用类模板的形参名声明类中的成员变量和成员函数,即可以在类中使用内置类型的地方都可以使用模板形参名来声明。比如template<class T> class A{public: T a; T b; T hy(T c, T &d);}; 在类A中声明了两个类型为T的成员变量a和b,还声明了一个返回类型为T带两个参数类型为T的函数hy。在类模板外部定义成员函数的方法为:template<模板形参列表> 函数返回类型 类名<模板形参名>::函数名(参数列表){函数体}。实例化一个模板类:类名<模板形参列表> 实例类名。 模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行。
32. C++预处理器
预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。实例中都有 #include 指令,这个宏用于把头文件包含到源文件中。
#difine 预处理:用于创建符号常量。该符号常量通常称为宏,指令的一般形式是:#define macroname replacename
参数宏:#define 来定义一个带有参数的宏,#define MIN(a,b) (a<b ? a : b)
33.C++多线程
多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。基于进程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行。多线程程序包含可以同时运行的两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程定义了一个单独的执行路径
创建线程:#include <pthread.h>  pthread_create(thread,attr,start_routine,arg ), pthread_create 创建一个新的线程,并让它可执行。
终止线程:#include <pthread.h>  pthread_exit(status), pthread_exit 用于显式地退出一个线程。通常情况下,pthread_exit() 函数是在线程完成工作后无需继续存在时被调用。
34. static关键字
1)全局静态变量
• 变量在全局数据区分配内存;
• 未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化);
• 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的;
2)局部静态变量
• 变量在全局数据区分配内存;
• 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
• 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
• 它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;
3)静态函数:
• 静态函数不能被其它文件所用;
• 其它文件中可以定义相同名字的函数,不会发生冲突;
4)类的静态数据成员
• 静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
• 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。在Example 5中,语句int Myclass::Sum=0;是定义静态数据成员;
• 静态数据成员和普通数据成员一样遵从public,protected,private访问规则;
• 因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它;
• 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为:
<数据类型><类名>::<静态数据成员名>=<值>
• 类的静态数据成员有两种访问形式:
<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>
如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员 ;
• 静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省存储空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了;
5)类的静态成员函数
• 出现在类体外的函数定义不能指定关键字static;
• 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
• 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
• 静态成员函数不能访问非静态成员函数和非静态数据成员;
• 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
• 调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
调用类的静态成员函数。
其中1-3是面向过程的,应用于普通变量和函数。4-5是面向对象的,类中的作用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++学习笔记(二) 的相关文章

  • 3D电视,你知道多少?

    1 3D电视常见知识 系统概述篇 1 什么是3D电视 xff1f 答 xff1a 3D电视是一种能够模拟实际景物的真实空间关系的新型电视 xff0c 它利用人眼的视觉特性产生立体感 xff0c 让观众感受到观看的影像是具有深度特性的三维立体
  • 程序员成熟的标志《程序员成长路线图:从入门到优秀》

    对好书进行整理 xff0c 把好内容共享 我见证过许多的程序员的成长 xff0c 他们很多人在进入成熟期之后 xff0c 技术上相对较高 xff0c 一般项目开发起来比较自信 xff0c 没有什么太大的困难 xff0c 有的职位上也有所提升
  • 前端工程师的价值体现在哪里?

    这是一个很老的话题 前端工程师的价值体现在哪里 xff1f 有人说 xff1a 前端工程师之于网站的价值犹如化妆师之于明星的价值 一位好的Web前端开发工程师在知识体系上既要有广度 xff0c 又要有深度 当然 xff0c Web前端工程师
  • 设计公共API的六个注意事项

    摘要 xff1a 俗话说 xff1a 好东西就要贡献出来和大家一起分享 xff0c 尤其是在互联网业务高度发达的今天 xff0c 如果你的创业公司提供了一项很酷的技术或者服务 xff0c 并且其他用户也非常喜欢该产品 xff0c 在这种情况
  • 从工具的奴隶到工具的主人

    摘要 xff1a 我们每个人都是工具的奴隶 随着我们的学习 xff0c 我们不断的加深自己对工具的认识 xff0c 从而从它们里面解脱出来 现在我就来说一下我作为各种工具的奴隶 xff0c 以及逐渐摆脱它们的思想控制的历史吧 当我高中毕业进
  • C语言 常用API

    MySQL的C语言API接口 1 首先当然是连接数据库 xff0c 函数原型如下 xff1a MYSQL STDCALL mysql real connect MYSQL mysql const char host const char u
  • linux下的C语言开发

    linux下的C语言开发 xff08 开篇 xff09 在很多人的眼里 xff0c C语言和linux常常是分不开的 这其中的原因很多 xff0c 其中最重要的一部分我认为是linux本身就是C语言的杰出作品 当然 xff0c linux操
  • C读写ini文件

    read write ini file with c function 64 file testini c chinayaosir blog http blog csdn net chinayaosir connect ini databa
  • 职场必知的20条黄金法则

    时间紧张 xff0c 先记一笔 xff0c 后续优化与完善 1 办公室里只有两种人 xff0c 角主和龙套 职场上 xff0c 想要过的省力 xff0c 不想往上爬 xff0c 那就只能做一生的龙套 作龙套的处坏就是 xff1a 死送你先去
  • 检测是浏览器还是手机,需求为是否支持FLASH,此文为检测是否支持FLASH的代码(含demo下载)

    步骤 xff1a 1 导入swfobject js文件 2 写一个函数 3 在需要用的地方调用方法 xff0c 此处为页面加载时调用 以下为示例代码 xff1a Java代码 lt script src 61 34 Public js sw
  • Jetson NX安装opencv3.2.0报错及问题汇总

    先放一个完整的cmake命令 cmake D CMAKE BUILD TYPE 61 Release D ENABLE PRECOMPILED HEADERS 61 OFF D CMAKE EXE LINKER FLAGS 61 lcbla
  • Ubuntu16.04环境下安装python3.8

    一 首先下载安装包 xff1a python官网 xff1a https www python org downloads 下载相应版本的python xff0c 如下图所示为Linux版本的安装包 二 配置依赖环境 xff0c 如果不进行
  • 超好用的网站推荐(持续更新)

    1 在线学习 1 1 网课学习 网易公开课 链接 xff1a https open 163 com 中国大学MOOC 链接 xff1a https www icourse163 org 哔哩哔哩 链接 xff1a https www bil
  • ROS基础篇(五)-- C++如何实现Topic & Service(roscpp)

    文章目录 1 Client library与roscpp1 1 Client Library简介1 2 roscpp 2 节点初始化 关闭与NodeHandle3 Topic in roscpp3 1 Topic通信3 2 创建Person
  • ROS基础篇(一)-- 最新学习路线,快从这里开始

    资料目录 ROS官网必看资料Diego Robot系列机器人开发目录古月居大神专栏创客智造系列博客文字补充 ROS官网必看资料 学习ros在查看国内相关资料的同时 xff0c 一定要学会首先翻看官网英文文档 xff0c 尤其是教程 Code
  • Git基础篇(二)-- Git安装与配置

    文章目录 1 下载与安装2 Git配置2 1 初始配置2 2 Git项目搭建 3 和服务器同步3 1 GitHub3 2 Gitee 参考 1 下载与安装 1 下载 打开 Git 官网 xff0c 下载 Git 对应操作系统的版本 xff0
  • Arduino基础篇(六)-- 如何使用Arduino的IIC总线(Wire)

    文章目录 1 IIC总线1 1 IIC概述1 2 IIC通信协议 2 Wire类库2 1 成员函数2 2 IIC连接方法2 3 主机写数据 xff0c 从机接收数据2 4 从机发送数据 xff0c 主机读取数据 1 IIC总线 1 1 II
  • ROS基础篇(八)-- Arduino中如何使用ROS自定义的msg

    使用rosserial arduino时 xff0c 总会面对多传感器的处理 xff0c 由于不同传感器的数据类型不同 xff0c 为了方便起见 xff0c 我们需要自定义数据文件 那么如何自定义的传感器数据 xff0c 并在Arduino
  • 多视图学习 (Multi-View Learning)

    1 介绍 多视图学习也称作多视角学习 xff08 Multi view learning xff09 是陶大成提出的一个研究方向 在实际应用问题中 xff0c 对于同一事物可以从多种不同的途径或不同的角度进行描述 xff0c 这些不同的描述
  • sklearn基础篇(三)-- 鸢尾花(iris)数据集分析和分类

    后面对Sklearn的学习主要以 Python机器学习基础教程 和 机器学习实战基于scikit learn和tensorflow xff0c 两本互为补充进行学习 xff0c 下面是开篇的学习内容 1 初识数据 iris数据集的中文名是安

随机推荐