以下是本人整理的C++基础知识点,内容并不包含全面的C++知识,只是对C++重点内容、特点进行整理和归纳。
思维导图链接:https://www.mubucm.com/doc/7E9Ilr_bznS
2.1 C++类的定义和对象的创建
类的定义
只是一种复杂数据类型的声明,编译后不占用内存空间
定义类时不能对成员变量进行初始化
用类创建对象
class 关键字可省略
class Student LiLei; //正确
Student LiLei; //同样正确
访问类的成员
栈上创建的对象 Stu stu;
有名字,可以用点号来访问成员变量和成员函数
堆上创建的对象(new)
没有名字,借助指针来访问它的成员变量或成员函数
pStu -> name = "小明";
2.2 C++类的成员变量和成员函数
类体内定义和类体外定义成员函数的区别
类体内定义成员函数
默认成为内联函数
一般不是我们所期望的
类体外定义成员函数
不会自动成为内联函数
建议的做法!
内联函数和非内联函数定义的区别
内联函数
直接在类内部定义
非内联函数
在类内部声明,在类外部定义
2.3 C++类成员的访问权限以及类的封装
访问限定符(限定来自外部的访问)
public
公开的
protected
受限的,在本类中使用相当于private
在该类的派生类内部可以访问该类的protected成员
private
私有的成员只能在本类内部使用,外部不能通过对象访问
成员没有限定符,默认为 private
类的封装的意义
封装,是指尽量隐藏类的内部实现,只向用户提供有限的、必要的成员函数
在语法上,private 关键字能更好地隐藏类的内部实现,向外暴露的成员都声明为 public
习惯性编程规范
成员变量:以m_开头
限定符使用
成员变量以及只在类内部使用的成员函数:声明为 private
外部使用的函数:声明为public
成员变量赋值的函数: set开头
成员变量读取函数:get开头
每一种限定符在类体中只出现一次
2.4 C++对象的内存模型
成员变量和成员函数的存储
成员变量
为每个对象的每个成员变量分配独立内存
在堆区或栈区
变量的内存顺序和声明顺序相同
成员函数
所有对象都共享同一段函数代码
在代码区
对象的内存所占用的内存大小
对象的内存组成
仅仅包含了成员变量,不包含成员函数
对象的大小只受成员变量的影响
对象的内存大小
等于成员变量占用的内存空间
2.5 C++函数编译原理和成员函数的实现
C++函数的编译
C++函数编译时的特点
根据它所在的命名空间、所属类、参数列表等重新命名,形成新的函数名
新函数名只有编译器知道,对用户不可见
编译中对函数重命名的过程叫做名字编码(Name Mangling),通过一种特殊的可逆算法实现
编译时的名字编码
一种特殊的可逆算法,对函数进行重新的命名,确保新函数名的唯一性
成员函数的编译和调用
成员函数的编译
成员函数被编译成与对象无关的全局函数
编译成员函数时要额外添加对象指针作为参数
成员函数和成员变量的关联
编译被调用的成员函数时,编译器把当前对象的指针传递进去,完成关联
通过对象调用成员函数时的隐式实现
不是通过对象找到函数,实际上是通过函数找到对象
因为函数调用时赋予了的当前对象的指针,关联了该对象
2.6 C++构造函数
构造函数的作用
在创建对象的同时为成员变量赋值
构造函数的定义和声明
声明或定义时,函数名前面不能出现返回值类型,函数体中不能有 return 语句
构造函数必须是 public 属性的,否则创建对象时无法调用
例子
构造函数的调用
构造函数的调用是强制性的
在类中定义了构造函数,那么创建对象时就一定要调用至少一个,不调用是错误的
创建对象时提供的实参必须和其中的一个重载构造函数匹配
创建对象时只有一个构造函数会被调用
构造函数的重载
如果有多个重载的构造函数,那么创建对象时提供的实参必须和其中的一个构造函数匹配
默认构造函数
如果用户没有定义构造函数,编译器会自动生成默认构造函数和复制构造函数
如果用户定义了构造函数,编译器不会自动生成默认构造函数
默认构造函数函数体是空的,也没有形参,也不执行任何操作
编译器的角度:实际上编译器只有在必要的时候才会生成默认构造函数,而且它的函数体一般不为空
默认构造函数的目的是帮助编译器做初始化工作,而不是帮助程序员
调用没有参数的构造函数也可以省略括号
Student *pstu = new Student()
Student *pstu = new Student
2.7 C++构造函数初始化列表
用法
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){...};
特点
使用构造函数初始化列表并没有效率上的优势,仅仅是书写方便
成员变量的初始化顺序
只与成员变量在类中声明的顺序有关
先定义a,就先给a赋值
跟初始化列表的顺序无关
初始化 const 成员变量
初始化 const 成员变量的唯一方法就是使用初始化列表
2.8 C++析构函数
析构函数特点
没有返回值,不需要程序员显式调用(程序员也没法显式调用),而是在销毁对象时自动执行
析构函数没有参数,不能被重载,没有返回值
一个类只有一个析构函数。如果用户没有定义,编译器会自动生成一个默认的析构函数
析构函数作用
销毁对象时系统会自动调用析构函数来进行清理工作
特别是有动态分配内存的场合,一定要自定义析构函数
析构函数的执行时机
全局对象
程序结束时调用析构函数
局部对象
函数结束时调用析构函数
动态对象
delete 删除时调用析构函数
2.9 C++对象数组(数组的每个元素都是对象)
对象数组中的每个元素都需要用构造函数初始化
构造函数有多个参数时,数组的初始化中要显式地包含对构造函数的调用
2.10 C++成员对象和封闭类
成员对象和封闭类介绍
成员对象:一个类的成员变量是另一个类的对象
封闭类:包含成员对象的类
封闭类对象本身的初始化
先执行所有成员对象的构造函数
成员对象构造函数的执行次序和成员对象在类定义中的次序一致,与构造函数初始化列表中出现的次序无关
然后才执行封闭类自己的构造函数
封闭类成员对象的初始化
特点
生成封闭类对象的语句,一定要让编译器知道成员对象如何初始化,否则会编译错误
有无参构造函数的,可以忽略其对象的初始化
方法1:借助封闭类的初始化列表
对于成员对象,参数表”中存放的是构造函数的参数
通过初始化参数列表的参数,编译器就知道调用哪个初始化函数来初始化
成员对象的析构
先执行封闭类的析构函数
然后再执行成员对象的析构函数
先构造的后析构
总结:反向次序,类似于出栈过程
封闭类的构造和析构本质
构造:入栈过程
成员对象1,成员对象2,封闭类对象
析构:出栈过程
封闭类对象,成员对象2,成员对象1
2.11 C++ this指针详解
特点
C++ 中的一个关键字,是一个指向当前对象的 const 指针,不能修改
对象被创建后 this 才有意义,不能在 static 成员函数中使用
定义时,成员函数中的this指针存在时机
在编译时被自动编进函数的参数列表中
调用时,this指针被赋值时机
编译时由编译器自动完成赋值
this指针的本质
是成员函数的一个形参,是成员函数的局部变量
在调用成员函数时将对象的地址作为实参传递给 this
在编译阶段发生和完成
2.12 C++ static静态成员变量
介绍
静态成员变量是一种特殊的成员变量,被关键字static修饰,没有初始化不能使用
所属上,static 成员变量属于类,不属于某个具体的对象
内存上,在全局数据区分配内存,所有对象都只使用同一份内存
static 成员变量不占用对象内存,即使不创建对象也可以访问
静态成员变量初始化(所有)
必须要初始化
必须在类声明的外部初始化
type class::name = value;
初始化不赋值,默认初始化为 0
int Student::m_total = 10;
静态成员变量访问
通过对象或类都可以访问
遵循 private、protected 和 public 关键字的访问权限限制
2.13 C++ static静态成员函数
静态成员函数和普通成员函数的区别
普通成员函数
有 this 指针
可以访问所有成员
只能在创建对象后通过对象来调用
因为需要this指针
静态成员函数
没有 this 指针
只能访问静态成员变量和静态成员函数
可以通过类来直接调用
2.14 C++ const成员变量和成员函数
const成员变量定义和初始化
定义:声明时加上 const 关键字
初始化:通过构造函数的初始化列表
const成员函数定义和初始化
作用
可以访问所有成员变量,但不能修改数值,用来保护数据
通常将 get 函数设置为常成员函数
const成员函数的声明和定义
在函数头部的结尾加上 const 关键字
char *getname() const;
必须在成员函数的声明和定义处同时加上 const 关键字
2.15 C++ const对象
介绍
常对象,不能修改其中的内容,所以只能调用类的 const 成员变量和 const 成员函数
常对象定义
const class object(params);
class const object(params); //这种可能是规范的
2.16 C++友元函数和友元类
友元作用
借助友元(friend),突破private限制,使得其它类的成员函数以及全局范围内的函数访问当前类的 private 成员
友元特点
友元的关系是单向的
友元的关系不能传递
友元函数
友元函数构造
在类外定义、在类中加上friend关键字声明,构成友元函数
可以是非成员函数,也可以是其它类的成员函数
友元函数特点
可以访问当前类中的所有成员
一个函数可以被多个类声明为友元函数
非成员函数作为为友元函数
声明
void show(Student *pstu){}//在类外定义
friend void show(Student *pstu); //在类中声明
访问
友元函数需要借助对象访问
因为友元函数不是成员函数,没有 this 指针
将其他类的成员函数作为为友元函数
声明
class Address; //提前声明Address类,并非正式声明
friend void Student::show(Address *addr); //类内声明
访问
友元函数需要借助对象访问
友元类
特点
将整个类声明为另一个类的朋友,所有成员函数都是另外一个类的友元函数
除非有必要,一般不建议把整个类声明为友元类
声明
friend class Student; //另一个类内声明
2.17 C++ class和struct
C/C++中struct的区别
C中的struct
只有成员变量,没有成员函数
C++中的struct
类似于class,既有成员变量,也有成员函数
兼容C中的struct用法
C++中的 struct 和 class 的区别
class
类中的成员默认是 private 属性
class 继承默认是 private 继承
class 可以使用模板
struct
结构体中的成员默认都是 public 属性
struct 继承默认是 public 继承
struct 不能使用模板
注意
用法上,struct完全可以当做class来使用,但是不建议
2.18 C++ string详解
string介绍
string 是 C++ 中常用的一个类,处理字符串更方便
包含头文件<string>
没有初始化的字符串默认值是""
string 的结尾没有结束标志'\0'
string操作
转换为C风格的字符串
用途
使用C语言中的 fopen() 函数打开文件,需使用C风格的路径
转换方法
转换函数 str.c_str()
将 string 字符串转换为C字符串,并返回C字符串的 const 指针(const char*)
string 字符串的输入输出
输入输出运算符
输入运算符:>>
默认会忽略空格,遇到空格输入结束
输出运算符:<<
字符串长度获取
str.length();//字符串的真实长度,没有'\0'
访问字符串中的字符
下标访问: str[5] = '5';
字符串的拼接
+或+=运算符来直接拼接字符串
string + (string , C字符串, 字符数组, 字符)
不用担心内存溢出
string 字符串的增删改查
插入字符串:insert()
删除字符串:erase()
删除字符串:erase()
提取子字符串:substr ()
字符串查找:find(),rfind(),find_first_of()
string的内部构造
string 隐藏了字符序列的物理表示,使用时不必关心数组维数或\0
string 在内部封装了与内存和容量有关的信息
开始位置、字符序列、长度
内存不足时,会自动调整
C++ 标准没有定义 string 类的内存布局,由编译器本身实现,但string 类的行为表现一致