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