C++理论知识
一. 面向对象
1. 面向对象的作用
在C语言的结构体中,结构体的设计思路是面向程序的,只能反映其若干属性,
而不能反映动作和方法,函数与数据结构是分离的,不适合体现出整体的关系,
同时不便于封装、代码重用和维护,以及缺少对数据的保护
2. 封装、继承、多态
- 封装:一方面使属性和方法形成一个整体,另一方面隐藏内部具体细节,对外提供特定的接口,
起到抽象和保护数据的作用,避免其他数据的干扰 - 继承:在已有的类上形成派生类,实现代码重用
- 多态:在派生的类中,存在名称相同、功能不同的方法,这样不必知道对象所属类就能执行多态行为
二. 基础知识
1. 内存
源程序经过编译形成可执行程序存储在硬盘上,运行程序时,需要开辟内存空间进行加载
内存分为五个部分:栈、代码段、数据段、堆、文字常量段
- 栈:存放局部变量、函数的参数
- 代码区:存放程序执行代码
- 常量存储区:存放常量,不允许修改
- 数据段(全局/静态存储区):存放全局变量或静态变量
- 堆:供malloc函数动态分配内存的空间,由free函数释放
2. 内存分配
malloc在堆空间中申请一块内存,使用malloc时,返回的是通用指针void*
int*p = (int*)malloc(sizeof(int)*length)
free(p)回收对应申请的内存空间
执行new的时候,首先分配未初始化的空间(malloc),然后调用对象的构造函数,并返回空间首地址
执行delete的时候,首先调用析构函数,然后使用free进行内存回收
之所以有new和delete,是因为malloc和free无法满足动态对象的要求
3.指针和引用
指针参数传递本质上是值传递,它所传递的是一个地址值
引用传递会通过一个间接寻址的过程对实参进行修改(即获得实参地址,访问时取地址进行操作)
4. define、const、static
cosnt定义变量时,意思是一个不能被更改的普通变量
define是宏定义,运行阶段不占据内存,预处理阶段将内容替换成定义值
static 修饰全局变量和函数时,把其作用域变成仅此文件可见,而无法被其他文件用extern访问
static 修饰局部变量时,其作用域不变,变量不存放在栈上,而是在静态数据区,生命周期延续至所有程序结束
static 修饰类:修饰变量则该变量为所有对象共有,修饰函数表示函数不属于任何对象,只能类内函数调用
const 修饰指针时,位于星星左侧,指针指向常量,位于右侧,指针本身是常量
const 修饰函数时,保护原有指针或引用不被外部修改,只能由类方法修改
const 修饰类对象时,常量对象只能调用常量函数
5. 函数重载、重写、重定义
C++可以使用默认形参值,在重载时要避免二义性
名字空间namespace避免函数变量重名
重载(overload):函数名字一样,编译器根据传入参数的类型和个数自动确定调用哪个函数的重载形式
重写(override):在派生类中重写基类中的虚函数
重定义:在派生类中覆盖基类中的函数
三. 类和对象
1. 类的结构功能
class 类名称{
public:
公共接口(在类外可以访问)
proteced:
受保护成员(类外不可访问)
private:
私有成员(类外不可访问,影响继承)
}
2. 构造函数和析构函数
类初始化和结束的时候,需要调用构造函数和析构函数来保证数据安全和独立性
构造函数不能有返回值,由编译器自动调用
- 无参构造函数:默认构造函数,函数为空
- 一般构造函数:重载构造函数,根据传入参数决定调用赋值
- 拷贝构造函数:未显示定义的情况下,进行浅拷贝(一一复制),当变量存在指针,需要自定义深拷贝函数(新建空间),防止内存泄漏
- 赋值运算符重载:对'='运算符进行深拷贝重载
构造函数中只能使用引用传递,否则会陷入无限循环
//运算符重载
class & class::operator=(cosnt class&类名){
if(this!=&类名)//防止自赋值
{
进行深拷贝
}
return *this;
}
3. 类和对象关系
内联函数:编译时宏展开,减少调用
关联关系:学生类和课程类之间的选课关系,这种关系被称作关联类
聚合关系:社团和和学生类之间的关系,不会同时析构
组成关系:汽车和轮子之间的关系,被拥有对象不能单独存在,同时析构
友元类和友元函数,允许其他类访问私有和受保护成员
友元关系不能传递、不能继承、单向
4. 继承和派生类
继承分为公共、保护、私有继承
基本语法为class 派生类名:继承方式 基类名
一般使用公有继承和保护继承,基类的私有成员在派生类中不可访问
派生类可以作为基类使用,基类指针可指向派生类
等号运算符不能被继承、友元关系也不能被继承
构造派生类时,会先构造基类同样析构时,先析构派生类,再析构基类
5. 虚函数和多态
在使用基类指针指向派生类对象时,删除对象会发生内存泄漏,这时仅析构了基类,需要使用虚函数来实现多态防止泄漏
使用虚函数实现了动态绑定,在运行时,能正确识别需要调用的类方法,以及进行析构
纯虚函数:像动物、鸟是一个抽象的概念,不具备实体,在基类中将函数定义为纯虚函数表示该类是一个抽象类,不具备实例
四. 运算符重载和模板
1. 运算符重载
在C++中运算符也被称为运算符函数,许多一元二元运算符都可以进行重载
一般有两种形式,重载为类的成员函数或友元函数,重载成友元函数,其参数表参数个数与实际参数一样多
2. 函数模板
对于不同类型的变量,只用一次定义函数即可,而不用多次实现重载版本
//比如两两交换
template<class T>void swap(T&a,T&b){
T c(a);
a = b;
b = c;
}
3. 类模板
以栈为例,可以在栈中存储任意类型的数据
templat<class T> class stack