C++ 进阶篇

指针数组
数组的元素是指针类型
Point *pa[2];
指针数组与二维数组的差别
指针数组的元素在内存中不一定连续,二维数组中的元素在内存中也是连续存放的
指针数组与二维数组的相同点 :逻辑上相邻

指针作为函数参数
优点
1.可以实现数据的双向传递(引用也可以)
2.需要传递一组数据或对象时 只传首地址运行效率高(如果不想传递的值被修改,那么可以使用const type& || const type*)

指针类型的函数
函数返回类型是指针类型
不要将非静态的局部地址用作函数的返回值(因为出了这个作用域这个对象就消亡了,内存空间被释放掉了)用new动态创建的对象不会自动消亡,必须要使用delete 关键字进行释放,否则会内存泄漏

指向函数的指针
函数指针指向的程序代码储存区 也就是函数的首地址
定义形式
返回值类型 (函数名)(参数列表)
int (
func)(int,int)
指向函数的指针用途:把函数当参数传(也就是C#中的委托)

对象指针
point *a;
对象指针访问数据 a->data 语法上等同于 *(a).data;

this指针
隐含于类的非静态成员函数中
指出成员函数所操作的对象
当通过一个对象调用成员函数时,系统首先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针

动态内存内配
动态申请内存操作符 new
new 类型名T(初始化参数列表)
分配成功返回T类型的指针,指向新分配的内存首地址,失败就抛出异常

释放内存
delete 指针p
释放指针p指向的内存 p必须是new 操作的返回值

动态申请数组
Point *p = new Point[2]; //数组访问元素 p[0]
释放动态数组
delete[] p; //记得写括号,不然只释放数组的首元素

动态多维数组
char (*cp)[3]; //表示定义了一个指向包含3个元素的一维数组的指针 cp指向数组的首地址
cp = new char[2][3] // cp指向首地址第一行 *(cp+1) = 数组的第二行

vector对象
封装任何类型的动态数组,自动创建和删除
数组下标越界检查

vector 对象使用
vector<元素类型> 数组对象名(数组长度)
vector<int> arr = {1,2,3}
v.begin() 获得头元素(迭代器)
v.end(); 最后一个元素

深层复制于浅层复制
浅层复制是将对象中的所有值都拷贝到复制的对象中,当对象中有指针时,此时两个对象指针指向同一内存区域,导致出现问题
深层复制,将对象或数组重新分配内存,然后将对象中的值复制过去,若对象中还有对象,那么继续执行深层复制

移动构造 (C++11新标准)
移动语义:源对象资源的控制权全部交给目标对象
classname(classname &&)
&& 右值引用 即将消亡的值就是右值 函数返回的值也是右值

C风格字符串
用字符数组来存放字符串
末位填 /0

string
构造string常用的构造函数
string();
string s1;
string(const char *s);
string s2 = "abc";
string(const string& s);
string s3 = s2;

输入整行字符串
getline() //要包括string头文件
getline(cin,s2) //从键盘读取数据,并保存到s2中
getline(cin,s2,',')//使用其他分隔符作为字符串结束的标志,第三个参数指定分隔符
两个参数的getline() 默认以换行符进行结束

继承
吸收基类成员 除构造函数于析构函数外所有成员
C++ 11中规定可以使用using语句继承基类构造函数

三种继承方式

公有继承
基类成员在子类中 pubilc protected 访问属性不变, private 不可直接访问
成员函数可以直接基类成员中 pubilc protected ,不可访问private,
派生的对象只能访问基类中public成员

私有继承
基类成员在子类中 pubilc protected 访问属性变成private, private 不可直接访问
成员函数可以直接访问基类成员中的 pubilc protected ,不可访问private,
派生的对象不能访问中基类中任何成员

保护继承
基类成员在子类中 pubilc protected 访问属性变成protected, private 不可直接访问
成员函数可以直接基类成员中 pubilc protected ,不可访问private,
派生的对象不能访问中基类中任何成员

usingB : B //使用using 继承基类构造函数

若不继承基类构造函数
派生类新增成员:派生类定义构造函数进行初始化
继承来的成员:自动调用基类的构造函数进行初始化
派生类的构造函数需要给基类的构造函数传递参数

单继承时构造函数定义语法
派生类名::派生类名(基类所需形参,本类中所需形参):基类名(参数表),本类初始化列表
{
其他初始化
}

多继承时构造函数定义语法
派生类名::派生类名(参数表):
基类名1(基类1初始化参数列表),
基类名2 (基类2初始化参数列表),
本类成员初始化列表
{
其他初始化
}

构造函数调用顺序
1.调用基类的构造函数 (按被继承的先后顺序调用)
2.对初始化列表中的成员进行初始化(顺序按照在类中定义的顺序,对象成员初始化自动调用其所属类的构造函数 由初始化列表传递参数)
3.执行派生类中构造函数体中的内容

派生类的复制构造函数

class A : class B
{
  //派生类没有自己实现复制构造函数的时候,调用派生类复制构造的时候,会主动调用基类复制构          
  //造函数
  //自己实现复制构造函数的时候,需要给基类的复制构造函数传参
  A(const &A):B(A)  //直接用派生类对象传递给基类复制构造函数
}

构造函数调用顺序
先调用基类的构造函数,然后调用派生类的构造函数

派生类的析构函数
调用顺序与构造时相反
先调用派生类的析构函数 ,然后调用基类的析构函数

派生类和基类中有相同成员
若无特别限定,则通过派生类对象访问的是派生类中的成员
若需要访问基类成员,则需要 基类名::成员名 访问基类成员
派生类.基类名::成员名 or 派生类指针->基类名::成员名

虚基类


C++中菱形继承.png

菱形继承产生冗余,并有可能因冗余带来不一致性
菱形继承虽然可以通过限定符消除二义性,但带来上存储空间上的浪费,对于一个类继承了两次

使用虚基类可以解决这个问题
对最远的派生类提供唯一的基类成员,而不重复产生多次复制
需要在第一级继承时就要设计共同基类为虚基类

虚基类的格式

class A:virtual public B  //(virtual 关键字)
{
  A():B(param);
}

虚基类的问题
虚基类的成员需要由最远派生类的构造函数通过调用虚基类的构造函数进行初始化
在整个结构中,只要继承了虚基类的派生类,都需要在构造函数中为虚基类列出参数
如果没有列出,那么默认调用该虚基类无参的构造函数
在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,其他类对虚基类构造函数的调用被忽略(写要写,调用只以当前创建对象的所属类来调用)

运算符重载
运算符重载可以有两种实现方式 1.类中成员函数 2.类外全局函数
运算符重载关键字 operator , 运算符重载依靠函数实现

双目运算符重载
Clock Clock::operator + (const Clock& c)

单目运算符重载
前置++重载 返回左值
Clock& Clock::operator ++();
//后置++ 返回右值 后置需要一个int类型的形参作为区分前置还是后置
Clock Clock::operator ++(0)

非成员函数的重载形式
Clock operator+(Clock &c1,Clock &c2)

虚函数
虚函数关键字virtual 给函数加上virtual 关键字 给编译器标识,编译器在静态绑定时不考虑此函数
实现动态绑定
虚函数需要实现动态绑定,则虚函数不能实现为内联函数,因为内联函数为静态绑定,编译阶段就需要处理,二者矛盾,所以虚函数不能为内联函数
虚函数属于对象,虚函数必须是非静态的成员函数
构造函数不能为虚函数,析构函数可以为虚函数

虚析构函数
在使用继承时,若基类指针使用运动时多态释放对象操作时,若析构函数不是虚函数,则会出现静态绑定,只调用基类的析构函数,而没有调用派生类的构造函数,此时需要将基类的析构函数定义为虚析构函数,进一步正确使用动态绑定释放资源,否则会内存泄漏


例子.png

虚表与动态绑定
动态绑定的实现机制


虚表.png

没个含有虚函数的对象,内部都包含一个指向虚表的指针vptr
若B继承A , A 对象指向A对象的虚函数 B对象指向B对象的虚函数,若B中没有实现A中的某虚函数,则B对象的该函数就指向父类的虚函数

抽象类
纯虚函数 是在基类中定义的虚函数,它在基类中没有定义具体的操作内容,要求派生类根据自己的实际需要定义自己的版本
virtual 函数类型 函数名(参数表)= 0 ;//等于零表示没有函数体
带有纯虚函数的类就是抽象类
抽象类无法实例化
派生类没有实现纯虚函数时,派生类也是纯虚函数类,也无法实例化,只有完成了对纯虚函数的实现,才可以实例化

OVERRIDE C++11新标准
显示函数覆盖
好处是 编译器会介入检查,使用了OVERRIDE后,会在基类中找同样的原型的虚函数
若找不到,编译器会进行报错

FINAL C++11新标准
FINAL 关键字 在类中使用,表示该类不能被继承
FINAL 关键字 在函数中使用 表示该函数不能被覆盖(重写)
Class A final {}
virtual void f() final

函数模板
template<class T > //作用就是与C#中的泛型

类模板
template<class T> //只能在头文件中写
class className<T>{}
类模板中的成员函数
返回值类型 className<T>::functionName(param);

STL简介
STL 标准模板库(Standard Template Libary)定义了一套概念,为泛型程序设计提供了逻辑结构

STL基本组件
1.容器
2.迭代器
3.函数对象
4.算法

IO流

输出流对象 ofstream
构造输出流对象ofstream

ofstream myFile("filename"); //指定文件名 默认打开

ofstream myFile;
myFile.open("filename") //构造函数不给文件名参数,可以使用open与文件建立关系

打开文件可以指定模式
ofstream myFile("filename",ios_base::out | ios_base::binary); //可以使用多种模式 使用多种时用按位或运算符

其他函数
put函数 //把一个字符写到输出流中
write函数 //把内存中的一块内容写到一个文件输出流中 二进制
close函数 //关闭一个文件输出流关联的磁盘文件
seekp 函数 //移动写指针
tellp 函数 //返回当前写指针位置

操纵符
流宽度
setw(n) //设置输出流对象cout 的输出所占字符 只影响后续字符 cout<<setw(1)<<n<<endl; 表示n只占一个字符的输出位置

setiosflags 流格式标识
定义在iomanip头文件中
setiosflags(ios_base::left) //设置对齐方式,影响后续所有字符 cout<<setiosflags(ios_base::left) //后续字符全部左对齐
resetiosflags(ios_base::left) //取消左对齐
setiosflags 可以使用 | 进行组合

精度 setprecision
在定点数格式 fixed 与科学计数法 下 精度表示为小数点后多少位
在其他情况下 参数表示有效数字位数 系统会根据数字大小 自动选择fixed 方式,或者科学计数法方式
setprecision(精度)

临时地址转换
reinterpret_cast
Date dt = {6,10,12};
reinterpret_cast<char *> (&dt);// 临时将dt地址转换为char 类型的指针

二进制文件流
ofstream file("date.dat",ios_base::binary) //二进制形式
file.write(reinterpret_cast<char *> (&dt),sizeof(dt));
file.close();

字符串输出流 (写)
ostringstream 用于构造字符串
可以将其他类型转换为字符串
支持ofstream 中除open,close 外的所有操作
str函数可以返回已经构造好的字符串

输入流类 (从文件中读)
istream 适合顺序文本模式输入 cin是其实例
ifstream类支持磁盘文件输入
istringstream

构造输入流类
ifstream myFile("filename"); //有参数 默认为打开此文件
ifstream myFile(); myFile.open("filename");// 与上述一致
打开文件时 也可以使用打开模式

字符串输入流
istringstream
支持istream中除open,close外的所有操作
可将字符串转化为数值

fstream 与 stringstream 都是由两个逻辑子流构成 可以交替读写

异常处理
throw type //抛出异常

try
{
//捕获异常
//捕获到异常,则后续代码不会执行
}
catch(exception e)
{
//异常处理,匹配异常类型,进入匹配的catch代码段
}

异常接口声明
可以在函数声明时列出这个函数可能抛掷的所有异常类型
void fun() throw(A,B,C,D)
没有异常接口声明,则可以抛出任意类型的异常
void fun() throw(); //列表为空,表示不抛出任何异常

异常处理中的构造与析构
自动析构
在try块中 创建的对象,由于发生了异常,导致后续代码不执行,创建的对象没有析构,按理说会造成内存泄漏
找到匹配catch块后,会从try块开始到异常被抛掷处之间构造的所有对象自动进行析构

标准异常类继承关系图.png
标准异常类含义.png

exception 标准程序库中异常类的公共基类(所有异常的爸爸)
logic_error 表示可以在程序中被预先检测到的异常
runtime_error 表示难以被预先检测到的异常

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容