1.面向过程:
完全兼容C语言
2.面向对象:
封装、继承、多态
类:一类事物的通用属性以及操作该属性的方法的一个合集,类是一种复合数据类型。
class demo
{
public:
demo(){};//若构造函数非公有,则为限制构造函数,该类无法创建对象
demo(demo & obj)//拷贝构造函数
{
val = obj.val;
cout << “demo() copy” << endl;
}
~demo(){};
void setInt(int val)
{
a = val;
}
void getInt();
protected:
private:
int a,b,c;
char *d;
};
void demo :: getInt()
{
cout << a << endl;
}
对象:类的实例化。demo obj; obj.成员
若定义了拷贝构造函数,则不可使用demo obj1 = 100;
拷贝构造函数:深拷贝:全部拷贝 ,包括内存。 浅拷贝:不复制数据,只复制指针,多个指针指向同一个内存
构造函数无this指针
用户调用析构函数时,只会执行函数体,并不会释放内存,等结束后才会再次调用析构函数释放资源
函数重载:函数名相同,参数不同(参数个数、类型),与返回值无关,可以设置默认参数,但默认参数的设置需要从右向左。
运算符重载: 返回值类型 operator 要重载的运算符 (形参列表){},可以进行运算符重载的函数 非静态成员函数、友元函数
运算符重载不能改变原有运算符的优先级和含义。
继承:代码复用,使另一个对象可以直接使用另一个对象的方法和属性
派生类的构造和析构时:构造先父类后子类,析构相反
解决多重继承引发的二义性:同名覆盖、加作用域、虚继承(菱形继承)
多态:
静态多态、动态多态
静态多态(函数重载)、动态多态(不同对象收到相同消息进行不同的动作)
函数重写(子类重写父类同名函数):函数头相同,父类必须含virtual关键字,访问限定符可以不同
函数重载(外部函数/成员函数均可):函数名相同,其余不同,无virtual关键字
函数隐藏(子类隐藏基类同名函数):函数名相同,其余可以不同,父类可以无virtual关键字
多态实现:必须有继承、派生类重写虚函数、通过基类指针或引用指向派生类对象调用虚函数
virtual使用限制:不能修饰普通函数,只能修饰类的非静态成员函数(不含构造函数)
虚函数实现原理:只要类中有虚函数或虚析构函数就会有虚函数表,就会有虚函数表指针指向其
虚析构函数:基类指针指向派生类对象,当基类指针要释放内存的时候,如果基类的析构函数没有加virtual关键字,则释放内存的时候不会调用派生类的析构函数释放资源,会发生内存泄漏
纯虚函数:一个虚函数只有声明没有定义,并且函数等于0.
eg:virtual void func()=0;
抽象类:包含纯虚函数的类,抽象类无法实例化对象。
3.泛型编程:编写与类型无关的逻辑代码,是代码复用的一种手段
模板 STL(标准模板库)
模板:使用时被参数化,根据实参类型产生函数或类的特定版本(模板本身不是函数或类)
函数模板
template <typename/class T>//说明T是类型参数
T add(T a,T b)
{
return a + b;
}
int main()
{
add<int>(1,2);//或add(1,2);
}
编译器会对模板函数进行俩次编译:声明时、调用时
类模板
template <class T>
class demo
{
public:
demo(const T val);
void setInt(const T val);
T getInt() const;
protected:
private:
T myval;
};
demo<int> a(100);
在类外定义函数必须加模板头,否则无法识别T
作用域必须加<T>,否则无法识别T
必须使用参数列表的方式赋值
非类型模板
在声明模板的时候比类模板和函数模板多一个普通参数
STL C++标准模板库
常用函数:
empty();判断向量是否为空
front();第一个元素
back();最后一个元素
size();元素个数
push_back(elem);将数据插入尾部
pop_back();删除尾部元素
begin();返回首元素
end();返回末元素的下一个元素地址
容器:
vector -> 向量模板类(本质是一个数组模板类) 连续存储的元素
list -> 链表模板类 双向链表
map -> 映射类 由{key,value}对组成的集合
deque -> 双队列 连续存储的指向不同元素的指针所组成的数组
set -> 集合
stack -> 栈 后进先出
queue -> 队列 先进先出
multimap -> 多重映射
priority_queue -> 优先队列
multiset -> 多重集合
迭代器:将算法和容器关联起来,起黏合剂的作用。
<iterator>
4.其余:
关键字、异常处理、转化函数、智能指针
引用:即变量的别名 int a = 0; int & b = a;
语言链接性:C++中使用C语言函数。extern “C” 函数声明 (放在.h文件)
new/delete运算符:动态申请和释放内存。
命名空间:namespace XXX {} 使用 using namespace XXX
输入输出流:cin/cout,C++标准输入输出对象,c:console;in:input c:console;out:output
this指针:只在非静态成员函数中默认存在,指代当前对象的首地址。构造函数无this指针。
关键字:
1)static
静态成员变量由该类的虽有对象共享访问,在类中声明,类外定义并初始化,只会分配一次内存。
静态成员函数无this指针,其属于整个类,可以通过类名::函数名方式调用
非静态成员函数可以访问所有变量,静态成员函数只能访问静态成员变量
2)const 受C/C++类型安全检查机制的强制保护,防止意外修改
const成员变量只能通过初始化列表方式初始化,之后无法改变
const成员函数关键字放在其后,不能修改任何成员变量的值
const对象所有成员都是只读的,不能更改成员变量
const引用把原对象所有成员变成只读,不能更改成员变量
const指针 同上
3)mutable 使成员变量不受const约束
4)explicit 只能修饰单参数的构造函数,防止其发生隐式类型转换(基本数据类型转化成类类型)
eg:demo obj1 = 10; --> demo obj(10);demo obj1 = obj;
5)final 类名或虚函数后加,加上后不可以被继承或重写
6)override 放在子类重写的虚函数之后,帮助检查虚函数是否一致
7)inline 内联函数,把频繁调用、函数功能简单、代码简短的函数定义为内联函数
由编译器决定是否编译为函数宏,使用时写在函数定义之前
8)virtual 主要用于定义虚函数、虚继承等,具有继承性(基类定义了virtual,子类该函数也就有了virtual属性)
9)volatile 防止编译器优化代码.eg: int volatile a = 10;
10)extern 在其他文件中声明变量
11)register 请求编译器尽可能将变量存在CPU内部的寄存器,register变量不能用&运算符来获取地址
12)malloc、calloc、realloc
malloc 申请内存未初始化,calloc申请到内存即将其初始化为0或NULL,realloc对申请到的空间进行调整,扩大空间时会尝试存现存的数据后追加字节不满足的话会重新开辟内存将现有数据拷贝到新内存处
友元:
友元函数 friend 返回值 函数();
友元类 friend class 类名;
异常处理:try(检查异常)-----throw(抛出异常)-----catch(捕获异常)
转化函数:
自定义转化函数: 只能是成员函数,无返回值和参数,不能定义成void类型、数组或者函数类型,常定义为const形式,其并不改变数据成员的值。
operator 类型名 ()
{
实现转化的语句;
}
标准转化函数:
- reinterpret_cast:不同数据类型的指针或引用之间的转换
- const_cast:把常指针或常引用转化成非常指针或常引用
- static_cast:基本数据类型之间的转换和具有继承关系的指针或引用之间
- dynamic_cast:具有继承关系的指针或引用之间
智能指针:
1 unique_ptr独享型智能指针:同一时刻只能有一个独享型指针指向堆内存
2 shared_ptr共享型智能指针:可以允许多个指针共享一块堆空间,当所有的智能指针被释放,堆空间才才会被释放
3 week_ptr弱型智能指针:不能单独存在,必须要和共享型指针一起使用,弱型智能指针的增加和消亡并不会影响堆内存的释放。