CPP回顾笔记

一、CPP回顾
1.面向对象是相对于面向过程更高级额一种编程思想
类:同一类对象的概述(人类)。举例 class CHuman;
对象:一个具体的实体(李白)。举例 Chuman objLiBai;

clas CHuman
{
public://公有类,谁都可以用
    void Fun(int nNum)
    {
       m_nNum = nNum;  
    }
protected://保护类,自己家人可以用
private://私有类,自己可以用
    int m_nNum;
};

2.与结构体的区别
区别:①默认的访问权限,类默认是私有的,结构体默认是公有的
②默认的继承权限,类默认是私有的,结构体默认是公有的
3.类的构造函数与析构函数
情况构造函数析构函数默认实现有有调用机制被动调动被动调用调用时机类定义对象时类对象被销毁时函数名与类名相同类名前加“~”返回值(函数类型)没有没有参数可以有没有函数重载可以不能虚函数不能可以
4.拷贝构造
举例 CHuman objA; CHuman objB = objA;
函数名与类名一致,分为浅拷贝(默认自带)和深拷贝。
深拷贝解决引用外部Buffer会导致错误复用的问题。
5.C++的静态概念
静态数据成员:带作用域的全局变量;
静态的成员函数:对外的接口。
6.引用
举例:int nNum = 15; int &pPtr = nNum;//(&nNum == &nPtr)&&(nNum == nPtr)
引用在定义时必须初始化,一旦初始化就不能引用其他变量(地址)
引用的本质,就是个一个变量(地址)起个别名
7.new和delete
情况newdelete功能申请堆内存空间释放堆内存空间构造析构调用构造函数调用析构函数
delete的单词调用析构与多次调用析构
举例:CHuman *pobj = new CHuman[10]; delete pobj; delete[] pobj;
delete pobj; //调用一次析构函数
delete[] pobj; //调用十次析构函数
8.默认参数
方式一:

void fun(int nNumA,int nNumB = 1 ,int nNumC = 5)
{
return nNumA+nNumB+nNumC;
}

方式二:

void fun(int nNumA,int nNumB = 1 ,int nNumC = 5)void fun(int nNumA,int nNumB ,int nNumC)
{
return nNumA+nNumB+nNumC;
}

二、定义常量枚举与内联
1.宏定义(define)
① 定义一个使用频率较高的常量
#define pi 3.14
② 给数据起名,使其有意义
#define up 1
#defne down 2
③ 有参宏实现使用频率较高的小功能
#define MUL(NumA,NumB) NumA*NumB
1.1 使用常量(const)代替无参宏
①声明了const之后,变量的值不可改变
②成员函数声明了const之后会导致不能修改数据成员

//当变量遇到const
const int g_nPI = 314;

int main()
{
//当指针遇到const
int nNumA = 0;
int nNumB = 0;
const int *p1 = &nNumA;//*p1 = 15;(×) 指针能修改,指向的值不能修改
int const *p2 = &nNumA;//同上 p2 = &nNumA;(√)
int *const p3 = &nNumA;//p3 = &nNumA;(×) 指针不能修改,指向的值能修改
}

1.2 使用枚举(enum)代替属性定义

//枚举实例
enum INFO
{
    up = 1,
    dowm,
    left = 8,
    right
}
// 1 2 8 9

1.3 使用内联(inline)代替有参宏
#define MUL(NumA,NumB) NumANumB ; //MUL(2,2+2) 结果6
inline int mul(int NumA,int NumB) NumA
NumB ; //mul(2,2+2) 结果8
2.类型转换
static_cast //静态类型转换
reinterpret_cast //强制类型转换
const_cast //常量类型转换
dynamic_cast //动态类型转换

//类型转换
char cNumA = nNum;
char cNumA = static_cast<char>(nNum);//静态类型转换
 
 char *pPtrA = (char*)nNum;
 char *pPtrB = reinterpret_cast<char*>(nNum);//强制类型转换
 
 char *pStrA = (char*)"Hello";
 char *pStrB = const_cast<char*>("Hello");//去掉常量属性
 
 //不建议使用
CStudent *pobjStuA = (CStudent*) new Chuman;
CStudent *pobjStuB = dynamic_cast<CStudent*>(new Chuman);//动态类型转换

3.友元(friend)
在类的权限控制上打穿一个洞,可以访问类内任意资源
3.1 友元函数
①就是一个全局函数,不属于任何一个类
②既可以类内定义,亦可类内声明,类外定义
3.2 友元类
假设类A是类B的友元,则类A可以访问类B的所有成员,反之无法访问;
假设类A是类B的友元类,类B是类C的友元类,类A与类C没有任何关系
举例:friend class CHuman;

class CApple
{
    friend class CHuman;//可访问CHuman所有成员
}

class CHuman
{
    
}

3.3 友元成员函数
假设类A的fun成员函数是类B的友元,则fun函数可以访问类B的所有成员
*注意先声明成员函数原型,后声明成员函数友元,最后定义成员函数
三、运算符重载
1.运算符重载的意义
简化编程,降低编程工作量,让代码简洁易懂,例如:
CStr objA(“hello”),objB(“world”); objA+objB == “helloworld”
1.1 加法的运算符重载(operator)
运算符重载不能创造新的运算符(例如将“**”解释为幂运算【×】)
运算符重载不能改变结合性与优先级
运算符重载不能改变操作数的个数
运算符重载不能改变语法结构
1.2 赋值运算符重载
赋值运算符重载函数,有一个默认的,执行的浅拷贝,必须以成员函数形式存在
1.3 自增自减运算符重载
1.4 下标运算符重载
1.5 流运算符重载
流运算符必须要使用普通函数的方式重载
2.类的继承深入探索
2.1 定义
主要是提供一种好用的代码复用机制,例如:
class CName:public Base1,public Base2, …
2.2 继承权限

总结:

  1. 父类是私有的,只能自己用,子类不能用;
  2. 子类是公有继承,除父类私有成员外,不会改变父类的其他成员权限;
  3. 子类是保护继承,除父类私有成员外,父类的其他成员属性均会变为保护;
  4. 子类是私有继承,除父类私有成员外,父类的其他成员属性均会变为私有。

2.3 重定义
普通函数:无论参数是否一致,只要符号名相同就会重定义;
普通变量:无论类型是否一致,只要符号名相同就会重定义;
类的成员:自类成员与父类成员只要符号名相同就会重定义,且子类会使用自己的成员;
其他情况:函数与比那两名的符号名相同,同样会发生重定义。
2.4 类的内存对齐
数据对齐的规则
Step1. 编译器有一个默认的对齐值(N=16)
Step2. 当向内存中摆放至i个数据时(当前数据大小M),在M与N中取最小值Ei
Step3. 使第i个数据摆放的位置是Ei的整数倍;
Step4. 当所有数据摆放完毕后,在E1、E2、…、En中取大小最大的数据体积值Emax
Step5. 是整个类的占用空间为Emax的整数倍。
2.5 类二义性问题
类继承的内存布局,父类在上面,子类在下面
2.6 通过虚继承解决二义性问题
3.多态
3.1 基本概念
静态:静态联编(调用关系编译时确定),例如函数的重载、重定义、模板;
动态:动态联编(调用关系运行时确定),例如虚函数
3.2 特点
通过父类指针对象指向子类(或通过父类的引用去引用子类对象),调用同名
的虚函数,如父类、子类皆有,则调用子类,如子类没有,则调用父类。
3.3 虚函数以及其内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值