IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++基本入门 -> 正文阅读

[C++知识库]c++基本入门

01第一个c++程序

02什么是对象

在这里插入图片描述

在这里插入图片描述
通过操作访问数据 数据是被保护起来的 对象其实就是变量 任何变量就是对象
通过外部操作改变data状态 而不是直接接触改变数据
在这里插入图片描述面向过程:事情发生的流程是怎么样,按照时间顺序一步一步会发生什么,即从时间顺序
面向对象:在某个场景中有什么东西,这些东西的关系是什么,比如一间教室里有灯,有学生,有老师等等,他们的关系是怎么样的,即从存在什么样的东西
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
设计就是找出思路的过程 实现就是写代码的过程 oo思想关注的是东西是数据而不是过程操作

03面向对象基本原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
object实体 class是种概念不是实体
在这里插入图片描述

oop特点
1万物都是对象实体
2程序就是一堆对象,告诉其他对象根据发送的消息做什么,(每个对象都给其他对象发消息告诉他们做什么而不是怎么做 要不要做)
3每个对象都有自己的内存,对象又是由其他对象组成的
c语言是一堆函数 调来调去回到main函数结束
4 每个对象都有类型 现有类型才有对象
5一个特定类型的所有对象可以接受相同的消息 比如所有水果都能被你咬一口有水喝
可以接受相同消息的对象可以归为同一类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
class creator 自己造的类 可以修改类里面的数据 但是client programmers可以调用类但是不能直接接触类中的数据 而是通过接口

在这里插入图片描述

三大特性:封装 继承 多态性

04自动售票机例子

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
按照过程模拟售票机 不合理 应该关注其内部有什么东西
在这里插入图片描述
在这里插入图片描述

img

#ifndef TICKETMACHINE_H_
#define TICKETMACHINE_H_

class TicketMachine
{
private:
const int PRICE;
int balance;
int total;
    /* data */
public:
    TicketMachine();
    virtual ~TicketMachine();
    void showPrompt();
    void insertMoney(int money);
    void printTicket();
    void showBalance();
    void showTotal();
};
#endif

#include "TicketMachine.h"
#include "iostream"
using namespace std;
TicketMachine::TicketMachine():PRICE(10)
{
}
TicketMachine::~TicketMachine()
{
}
void TicketMachine::showPrompt()
{
    cout << "something";
}
void TicketMachine::insertMoney(int money)
{
    balance += money;
}
void TicketMachine::showBalance()
{
    cout << balance;
}
#include "TicketMachine.h"
int main()
{
    TicketMachine tm;
    tm.insertMoney(100);
    tm.showBalance();
    return 0;
} 

在这里插入图片描述

::"类作用域操作符。“::"指明了成员函数所属的类。如:M::f(s)就表示f(s)是类M的成员函数。
::a++ 前面没有类名 表示是全局的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
![(https://img-blog.csdnimg.cn/20201028134324929.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZW9uZw==,size_16,color_FFFFFF,t_70#pic_center)
在这里插入图片描述img
源代码.c/cpp------>可执行文件.out/exe

预处理生成.i
预处理生成.ii
汇编文件.s
生成二进制.o
链接成可执行文件.out/exe // 多个.o目标文件链接后生成可执行文件

g++ –E main.cpp // 生成.i
g++ –S main.i main.s // 由.i生成.s
g++ -C main.cpp // 生成.o二进制目标文件 .cpp—>.o
g++ main.o -o AA // 由.o目标文件到可执行文件AA.out/exe .o—>.out/exe
g++ main.cpp // 编译连接一起,生成可执行文件a.out/exe .cpp–>.out/exe
g++ main.cpp -o AA // 由.cpp源文件到可执行文件AA.out/exe
在这里插入图片描述
编译程序时 c++只对.cpp进行 只看到一个.cpp文件 看不见其他东西
对头文件 我们只能声明而不能放定义

声明有:extern 变量 函数的原型 class/struct的声明 (只有声明无定义)

int a//定义
extern int a//声明
f()//函数的定义
f// 函数原型即声明
在这里插入图片描述
在这里插入图片描述
自动生成的标准头文件结构 为了防止在一个.cpp文件中 include一个头文件多次而出现那个.h类的声明被重复出现
在这里插入图片描述
一个头文件只放一个类的声明 而其对应的源代码文件用相同的前缀 把后缀改成.cpp 里面放着它所有函数的body(definition) 头文件要用标准头文件给 只能include 声明而不是定义

06时钟例子

抽象 :看待某件事物 有意的看不见一些细节 只会在某个层次看 把进一步的层次屏蔽起来,比如看见一辆车 你就想到大小 颜色 等等 不会去考虑里面座椅皮质是什么材质 轮胎尺寸等等
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

07成员变量

假如在某个函数中定义了一个本地变量 和成员变量的名字相同 c语言就是按照最近原则来 所以本地变量起作用 屏蔽成员变量

在这里插入图片描述

fields成员变量(字段) parameter参数 localvariable本地变量

成员变量值和函数无关 只要对象在他就在
成员变量的作用范围是类的范围 类中的成员函数可以使用这些成员变量
本地变量只能在他的那个函数使用

08成员变量的秘密

声明不告诉这个变量在哪里 只是告诉有这么个东西
类不是实体 只有实体才有变量 如a是实体是对象 才有i这个变量
而函数是属于类的 不是属于对象的 f是A的函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
B中无f函数 只能f(&b)

在这里插入图片描述
在这里插入图片描述
f是类的 i是对象的
cout<<a.i 先输出a.i=10
进入a.f() 先输出10 又因为f内i=20 所以输出20
此时输出a.i 变成20 输出20
再申请f(&b) 输出20

在这里插入图片描述

在这里插入图片描述
a的地址和a.i的地址和f()内i的地址一样 所以调用a.i a.f()时地址都是a的 这个联系建立是通过this
在这里插入图片描述
在这里插入图片描述this可以被隐藏的 this是个指针 可以看出f()和this 的地址同
i=20 也可写成this.i
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

09构造和析构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
构造函数(构造器)和类的名字一样而且没有返回类型
这个构造函数会在对象被创建的时候就自动被调用
当你有个对象a时 即X a就会做a.X();

在这里插入图片描述
把对象传给构造函数

在这里插入图片描述
在这里插入图片描述
析构函数 对象结束之前要调用析构函数 析构函数不能有参数 和类名一样 但是前面有~ 析构意味着收回空间
几个对象就是几个析构函数
在这里插入图片描述
在这里插入图片描述
会在before opening brace 之后马上调用构造函数 在构造对象之前
会在after closing brace 之前马上调用析构函数 在结束对象之前

在这里插入图片描述
x1的空间进了f的{}就有 但是因为到了jump1 x1就没有调用构造函数 只有X x1的时候构造才会做 但是跳出{}就会析构x1 但是x1并没构造 所以编译无法通过 会出现问题

10对象初始化

在这里插入图片描述
sizeof c/sizeof *c 求数组c的个数
在这里插入图片描述

缺省 没有参数的构造函数是 default constructior
Y y2[2]={Y(1)} 错误的 因为没给第二个数 相当于告诉编译器去找个default constructior来初始化这个对象 编译器就说 找不到 因为没有

10new和delete

在这里插入图片描述
new 要做:1分配空间2调用构造函数 如int只要分配空间即可 类stash在分配空间完后需要调用构造函数 对象被创建的时候一定会调用构造函数 不论是堆里面的变量还是本地变量 3预算符要有结果 所以返回的是这个空间的地址

new 先分配空间 得到空间再去里面做初始化
delete是先析构 析构完再收回空间

在这里插入图片描述
在这里插入图片描述

delete [] psome是整个数组 不带[]只会调用第一个元素的析构函数 而不是所有元素的
在这里插入图片描述

一张表inchtable 记录这块内存的地址 这个内存有多大

在这里插入图片描述

#include <iostream>
using namespace std;
class A
{
private:
    int i;
    int *p;

public:
    A()
    {
        p = 0;
        cout << "A::A()" << endl;
    }
    ~A()
    {
        delete p;
        cout << "A::~A" << i << endl;
    }

public:
    void set(int i) { i = i; }
    void f()
    {
        p = new int;
    }
};
int main()
{
    A *p = new A[10];
    for (int i = 0; i < 10; i++)
    {
        p[i].set(i);
    }
    delete[] p;
    return 0;
}

假设r是数组
其中delete r 表示只调用了第一个元素的析构函数 但是整个r数组的空间都被收回了
delete r[] 会调用每个元素的析构

在这里插入图片描述
注意要new就要delete 虽然在平时作业中进程结束就会终止不会造成影响 进程结束这片内存会被回收 但是如果不是作业就会造成内存泄漏

12访问限制

在这里插入图片描述

oop对象是封装的是被保护的 能接触的只有函数 可以通过函数来要求做什么 但是具体怎么做对数据产生什么影响是代码影响 使用类的程序员(client programmer)不能访问类里面的东西 而对写类的人(Libary designer )可以修改内部的东西而不至于影响别人

在这里插入图片描述
这些权限是指在编译层面的 只在编译时刻检查 是真对类的限制 不是对对象

  • 运行时刻如果有办法的话可以不受限制
    public 任何人可以访问
    private 可以是函数或者变量 只有自己可以访问 即这个类的成员函数可以访问
    protected
    在这里插入图片描述
    在这里插入图片描述
    class vs struct
    class defaults to private
    struct defaults to public

13 初始化列表

在这里插入图片描述
在这里插入图片描述

构造函数的初始化和赋值
赋值做了两件事 先初始化再赋值 只是初始化的时候是用默认的构造器初始化
但是一般编程习惯是在构造函数中初始化

14对象组合 (拿已有对象去拼装新的对象)

三大特性 封装继承多态性

继承是软件重用的回答 或者 继承是实现软件重用的方式
在这里插入图片描述

by reference表示别的对象不是身体本身的一部分 而是其他的 宝宝出生后单独个体 by reference 成员变量是个指针
fully 表示这个对象就是本身的一部分 完全包含 宝宝在肚子里 fully

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

虽然类saving account里面有类 person和currency 但是初始化和调用函数时不能直接拿这两个类的东西 要通过他们定义的对象 m_saver和m_balance 来调用

15继承

组合是拿对象(object)拼出新的对象 实(对象是实体)
继承是拿类改造一下 造出新的类 虚(类是概念)在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
superset超集 student is a superset of person student是个继承者

在这里插入图片描述
manager is a emploee sub 子类 derived派生类 B继承于A 则有A的任何一切 拥有但是不代表可以直接使用private的东西 只能通过父类的某些函数去使用这些私有成语(比如set print)

#include <iostream>
using namespace std;
class A
{
public:
    A(int ii) : i(ii) { cout << "A::A()" << endl; }
    ~A() { cout << "A::~A()" << endl; }
    void print() { cout << "A::print()" << i << endl; }
    void print(int i)
    {
        cout << i;
        print();
    }
    void set(int ii) { i = ii; }

private:
    int i;
};
class B : public A
{
    //若没有public 默认private
    //struct 默认public
public:
    B() : A(15) { cout << "B::B()" << endl; }
    ~B() { cout << "B::~B()" << endl; }
    void print() { cout << "B::print()" << endl; }
    void f()
    {
        set(20);
        //i = 30;
        print();
    }
};
int main()
{
    B b;
    //b.set(10);
    b.print();
    b.f();
    b.print(200);
    return 0;
}

在这里插入图片描述
这里B中 直接令i=30 会报错

在这里插入图片描述
建立某个类时 首先所有数据都是private 要给所有人要用的放在public 留一些protected的接口给子类 告诉子类可以通过protected的东西直接访问一些private的东西 这手段只留给子类 别人不能做

在这里插入图片描述

16父类子类的关系

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

加上std::是这个类的全名 因为以前用了using namespace std;
在这里插入图片描述
两个print函数构成重载关系 overload 因为参数不一样

在这里插入图片描述
现在B是A的子类 B中有A的body 所以B要初始化时候,就要遵循A的规则让A自己把自己的那部分初始化 有父类的对象 必须让父类对象初始化 所以父类的构造会被调用

在这里插入图片描述

在这里插入图片描述
如图 B要构造自己的析构函数时候 必须借助A的构造函数 所以先调用A的构造再调用B的 析构是先B后A
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

父A子B中都有print函数 且A中有重载函数 B中的f也有print函数这个print函数与A中的某个一致(指的是名字参数表一样 )namehidding 名字隐藏 则父类的其他同名函数隐藏了 只有子类自己定义的这个 所以当要调用B.print(20)是不合法的

#include <iostream>
using namespace std;
class A
{
public:
    A(int ii) : i(ii) { cout << "A::A()" << endl; }
    ~A() { cout << "A::~A()" << endl; }
    void print() { cout << "A::print()" << i << endl; }
    void print(int i)
    {
        cout << i;
        print();
    }
    void set(int ii) { i = ii; }

private:
    int i;
};
class B : public A
{
    //若没有public 默认private
    //struct 默认public
public:
    B() : A(15) { cout << "B::B()" << endl; }
    ~B() { cout << "B::~B()" << endl; }
    void print() { cout << "B::print()" << endl; }
    void f()
    {
        set(20);
        //i = 30;
        print();
    }
};
int main()
{
    B b;
    //b.set(10);
    b.print();
    b.f();
    b.print(200);
    return 0;
}

17函数重载与默认参数

在这里插入图片描述
函数重载就是 同名 参数列表不同 (类型 个数等等)
在这里插入图片描述

预先给一个值 缺省参数 所以stash 有两种写法 给一个值或给两个值
一定要从最右边省略过来 写在声明里不写在定义里 即可以缺省可以写在.h里面 不可以写在.cpp里面

在这里插入图片描述

default argument是发生在编译时刻 尽量不要使用default value

18内联函数(inline)

overhead 额外的开销
在这里插入图片描述
在这里插入图片描述

内联函数不会像函数调用那样经历push pop等操作 而是相当于会把这段函数代码嵌入这个地方 (在编译的时候这么做) 而仍保持函数的独立性 有函数的空间等等

在这里插入图片描述
在这里插入图片描述
左边是函数调用 右边是内联函数 二者的汇编对比
在这里插入图片描述

inline 必须在声明和定义中都要有。
.cpp是用来产生函数的 .h是给调用这个函数 的地方看的

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
左边是c的宏 他检查不出double的错误 而inline可以检查出double的错误

在这里插入图片描述
inline不一定会给你插入 如果你有很大的循环或递归的话 编译器就会拒绝

#include <string>
#include<iostream>
using namespace std;
class Point
{
    int i, j, k;

public:
    Point() { i = j = k = 0; }
    Point(int ii, int jj, int kk)
    {
        i = ii;
        j = jj;
        k = kk;
    }
    void print(string msg =" " )
    {
        if (msg.size() != 0)
            cout << msg << endl;
        cout << "i = " << i << ", "
             << "j = " << j << ", "
             << "k  = "<< k << endl;
    }
};
int main()
{
    Point p, q(1, 2, 3);
    p.print("value of p");
    p.print("value of q");
    p.print(); 
}

在这里插入图片描述
在这里插入图片描述
类里面的函数body放里面则自动变inline 如point() point(ii jj kk) print都是inline
在这里插入图片描述
所以不会真的调用 只是把代码插到这里来

#include <iostream>
using namespace std;
class Cup
{
    int color;

public:
    int getColor() { return color; }
    void setColor(int color)
    {
        color = color;
    }
};

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
函数的body写在类外 比较清爽

在这里插入图片描述

19 const (保证初始化后不能被修改、赋值)

在这里插入图片描述

在这里插入图片描述
const是变量
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

const位于的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;所以修改p不可以 指针所指的内容不可以改

const位于*的右侧,则const就是修饰指针本身,即指针本身是常量。q++不可以

星号前是对象是const 写在星号后指针是const
在这里插入图片描述

1 p 即指针所指的内容不能修改
2 对象是const
3p指针不能修改 所以p++不对 p的地址不能改
在这里插入图片描述
int *p 一个普通指针
const int*cip 一个指向const变量的指针 即他所指的变量不能通过他修改的指针
尽管 *cip就是i(因为cip=&i 所以*cip=

&i=i) 但是永远不能写cip=xxx //错误!
cip=&ci 正确 因为保证了 ci不会通过cip这个指针所修改 因为const int

cip 一个指向const变量的指针 即他所指的变量不能通过他修改的指针

#include <iostream>
using namespace std;
int main()
{
    //char *s = "hello world";
    char s[] = "hello world ";
    cout << s << endl;
    s[0] = 'B';
    cout << s << endl;
                
    return 0;
}     

在这里插入图片描述
在这里插入图片描述
hello world是常数所以放在代码段内 char*s 实际上是const类型的 所以他不可以被就修改
所以s[0]='B’无效
在这里插入图片描述
在这里插入图片描述

s1在代码里面 与main距离很近 s2在堆栈内
在这里插入图片描述
一个函数f的参数类型是 int* 则无论给他什么类型的int都可以 不管是不是const 所以可以保证对传进来的参数不修改

在这里插入图片描述
表明在f1内不能去改i的值

在这里插入图片描述
值可以赋给非const 的变量 因为并不是要改变他

在这里插入图片描述
通常直接传递一个变量开销很大因为要放堆栈中 所以最好是传地址 但是又不希望所指的内容被修改 所以加const以const身份对象传给你 保证他不被修改 是安全的

在这里插入图片描述

在整个大对象前面加了const 这个对象的值就不能被修改 返回值为常量不能作为左值 整个对象就是const 一旦这么做以后 这个对象的函数就有问题了 因为成员函数可能会修改成员变量
.h只有函数原型 .cpp才有函数body main.c include了.h文件他在编译的时候可以知道整个函数的原型但不知道body 这样就不知道到底哪些成员函数会修改成员变量

一个函数后面有const:在成员函数后面加上const 保证他不去修改任何的成员变量 需要在原型(这样编译器就能检查出来 成员变量是安全的可以用的 )和定义的地方都要加上const
在这里插入图片描述

在这里插入图片描述

20不可修饰的对象

在函数后面写const 即this是const

#include <iostream>
using namespace std;
class A
{
    int i;

public:
    A() : i(0) {}
    void f() { cout << "f()" << endl; }
    void f() const
    {
        cout << "f() const" << endl;
    }
};
int main()
{
    const A a;
    a.f();
    return 0;
}

在这里插入图片描述

void f(){...} 等价于 void f(A* this){...} 
void f() const{...} 等价于voide f(const A* this) const{...} 
所以a.f()调用的是第二个函数  因为const A a
二者构成overload的关系 因为实际上他们的参数列表不一样

12345

在这里插入图片描述
在这里插入图片描述

如果成员变量 定义const int i i是const 则i必须在构造函数中初始化 否则会报错 A() {} 不行
必须 A():i(0){}

在这里插入图片描述
const 不能做数组的size

21引用

c++提供了太多可以放对象的地方 1可以放在堆栈里面 2堆里面 3全局数据区里面
提供了太多可以访问对象的方式 1直接掌握一个对象 ,变量里面是对象 2通过指针访问一个对象 3通过引用访问一个对象

在这里插入图片描述
引用时在定义需要给一个初始值 以表明这个r是c的引用 初始值必须是个变量或是一个可以做左值的东西 r就是c的reference r是c的一个别名
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;
int main()
{
    int x = 47;
    int &y = x;
    cout << y << endl;
    y = 18;
    cout << x << endl;
}

reference的理解 1—y就是x的另一个名字 以后出现y的地方都可以换成x
在这里插入图片描述

引用的初始化会建立一个联系

const int& z=x  z是x的一个别名但是通过z你不能修改x  但是x依然可以改变  
与const int* p=x同  也不能通过p修改x  即不能让z或p做左值
12

引用的目标必须有个位置放他 如i3有结果 但是没有一个有名字的变量(位置 )去放i3这个结果

在这里插入图片描述

在这里插入图片描述

f(int* x){*x)++//x指针所指的内容++
  
}


123456

在这里插入图片描述
因为q是在本地变量 返回q是error return q错误
和用指针返回本地变量的地址一样不正确

x是全局变量可以 return

在这里插入图片描述

#include <iostream>
using namespace std;
int *f(int *x)
{
    (*x)++;
    return x;
}
int &g(int &x)
{
    x++;
    return x;
}
int x;
int &H()
{
    int q;
    return x;
}
int main()
{
    int a = 0;
    f(&a);//Ugly(but explicit)
    g(a);//Clean(but hidden)
}
一个函数返回的类型是 &reference 就可以做左值
因为 int& h(){..
}
所以 可以h()=16成立 这使得x=16 因为h()是返回x 且是个reference
1234

在这里插入图片描述
alias 别名

int x;
int &a=x;int &b=a ;错 没有reference的reference

想要b=a
需要
int x,Y;
int &a=x;
int &b=y;
b=a;

reference 两种含义 1一个变量的别名 2实际是种const 指针

在这里插入图片描述

int&* p;//以为是星p的reference的   即p可以取到reference的地址但是实际上reference不能取 


int*& p  //p是reference 所捆绑着变量是个int* 指针

type& rename;
int* & p;
1234567

22向上造型

在这里插入图片描述

把子类的对象当做父类的来看待
比如学生和人 把学生看出人 学生多出来的东西当做不存在
因为指针所指的地址的便宜都是一样的 就算子类有多出来的东西也是在之后加上去的

在这里插入图片描述
upcast一定是正确的 (子类指向父类)downcast有风险 比如你随便找个人不一定就是学生

类型转换和造型的区别:
类型转换 比如double变int 就完全丧失了double的特性
造型 比如学生还是学生 只是我们看待他的眼光变了 不在当他是学生 把他当人看 他的类型没有变所以不是类型转换

在这里插入图片描述
当通过 ep指针输出的print是employee的print 而不是manager的 (不是之前说的那个name hiding)

23多态性

在这里插入图片描述
在这里插入图片描述
circle rectangle ellipses都有共同的成员函数和成员变量

identical 同样的事物 render提供 渲染
在这里插入图片描述
在这里插入图片描述
父类中的virtual 使得子类和父类的同名函数产生了联系 这样后代继承的render也是virtual

在这里插入图片描述

major_axis  minor_axis 长轴短轴
1

在这里插入图片描述

virtual 通过指针或者引用去调用这个函数的时候 去调用render时 不能直接写进来去调用哪个函数 要到运行的时候才能决定 p所指的render是通用的 对任何shape的子类都适用

p是多态的 p指的是谁 就变成谁的动作

在这里插入图片描述

静态绑定 调用的函数在编译的时候就是确定的知道的
动态绑定 在运行的时候才知道调用哪个函数 根据指针所指的对象决定去调哪个函数

在这里插入图片描述

p->render () 因为render是virtual 所以render 可以是ellipse circle的render 所以是动态绑定
但如果是p—>move() move()不是virtual 所以move是shape的

24多态性的实现(virtual)

在这里插入图片描述
在这里插入图片描述

任何类中只要有一个虚函数 只要有一个 他的对象都会比一般的大一点

sizeof(a) 为8 因为是int型
int* p =(int*)&a; //p是变量名 是指针型的(int*型的) 所以传a的地址
p++ 后 *p是10 //*p是指针所指的内容

在这里插入图片描述
有virtual类的对象的的里面 头上会加上一个隐藏的指针叫vttr 他指向一张表叫vtable vtable里面是他所有virtual的函数的地址 vtable是这个类的不是对象的 这个类的所有vttr的值都是一样 在这里插入图片描述
在这里插入图片描述
当使用指针或引用时才会产生动态绑定,通过点去调用不会
在这里插入图片描述

在这里插入图片描述

#include <iostream>
using namespace std;
class A
{
public:
    A() : i(10) {}
    virtual void f() { cout << "A::f()" << i << endl; }
    int i;
};
class B : public A
{
public:
    B() : j(20) {}
    virtual void f() { cout << "B::f()" << j << endl; }
    int j;
};
int main()
{
    A a;
    B b;
    A *p = &b;
    p->f();
    return 0;
}
p->f();//调用的是b的f 输出B::f()20
a=b;//因为b是a的子类 所以让b赋值a 合理
但是通过a.f() //输出输出A::f()10 这样调用的是a的f() 虽然f是virtual但是不是通过指针或引用来动态绑定的 所以即使a是由b赋予的 还是调用的A的f



若当
a=b;
p=&a;

p->f();//输出A::f()10 这样调用的是a的f() 因为b只是把值给a 地址并没有传给vttr a的vttr并没有被改变 所以a还是a  所以即使b先赋给a p再取a的地址 a的地址始终是没有变化的

123456789101112

在这里插入图片描述
若如上图 理应输出B::f() 20
但是实际输出的B::f() 32767
在这里插入图片描述
图上写错 应输出B::f()

在这里插入图片描述
因为只是值的传递 所以circ即使赋给elly 调用elly.render 也是ellipse的render 不会是circle 的render 理由同上

在这里插入图片描述
在这里插入图片描述

但如果是指针的话 这样指针的指向改变了 elly就被赋予了circ elly指向circ 所以elly->render() 就是circle的render

在这里插入图片描述
如果是引用的话 耶同理 如果传给func的是circ的话 调用是的circle 的render

如果一个类里面有一个virtual函数 那么他的析构函数必须是virtual 否则会有麻烦

在这里插入图片描述

c++默认是静态绑定 其他op语言默认是动态绑定的 所以c++要加上virtual(为了效率)

在这里插入图片描述

override 覆盖或改写 :父类子类的两个函数名称相同参数表也相同 称为override

在这里插入图片描述

如果需要调用父类的func可以写成 base::func()

在这里插入图片描述

在这里插入图片描述

如上 同样的函数 子类返回了子类的指针 返回了指针的引用可以 但是不能返回对象本身自己 因为只有通过指针或对象才能发生upcasting关系

在这里插入图片描述

如果你在父类有两个virtual的overload的函数 那么你在子类也必须override所有virtutal函数的overload的函数 否则另外的函数会发生namehidding 只有c++这种oop语言存在namehide 其他语言不存在

25引用再研究(const &)

如果一个类的成员是reference 必须使用构造函数的列表初始化
在这里插入图片描述

在这里插入图片描述

引用作为返回值
在一个函数内不能返回本地变量的地址作为指针或reference 必须返回全局变量

在这里插入图片描述

double value=subscript(12)虽然左边是double 右边是reference 看起来类型不匹配 
其实实际上就是把myarray的值赋给value

subscript(3)=34.5 //表面上看是subscript的返回值是34.5  实际上是这个返回值带回的那个变量等于34.5 即myarray[3]=34.5  所以一个函数的返回值的reference是可以做左值的 
1234

在这里插入图片描述

加上const 把这个对象送进函数 保证函数无法通过指针来修改这个对象 但是指针用星号不方便
所以当我们需要穿对象进一个函数的时候 我们用const reference

在这里插入图片描述

如上图y是const reference 不能被修改 不能做左值
1

在这里插入图片描述

func(i*3)func要的是reference 要有具体的变量名 i*3不能做左值
因为i*3 会产生const int reference的临时变量 tmp
但是func接收的是int &类型  而不是const int 
如果func接收的是const int&类型 则func(i*3)可以
因为一个是const int &一个是int &


在这里插入图片描述

26拷贝构造(浅拷贝 深拷贝)

在这里插入图片描述
将currency的对象作为输入

在c++必须分清两种概念 定义和声明 即definition和declaration 还要分清初始化和赋值

currency p=bucks//initialization 
p=bucks//assignment

在声明这个变量的时候 前面有变量类型就是定义  给变量一个值叫initialization
已经定义好变量了 你再给他值叫assignment 
    
#include <iostream>
#include<string>
using namespace std;


static int objectCount=0;
class howmany{
	public:
		howmany(){objectCount++;print("hommany()");}
	// howmany(int i){objectCount++;print("hommany(int)");}
	//如果在定义一个带int的构造函数时,之后在main里面
	//howmany h2=10;和howmany h2(10)就是等价的 输出的结果完全一样
		void print(const string& msg=""){
		    if(msg.size()!=0) cout<<msg<<":";
		    cout<<"objectCount="<<objectCount<<endl;
		}
		~howmany(){
			objectCount--;
			print("~howmany()");
		}
		
}; 

howmany f(howmany x){
	
	cout<<"begin of f"<<endl;
	x.print("x argument inside f()");
	cout<<"end of f"<<endl;
	return x;
	
}
int main(){
	
	howmany h;//进入这句产生了hommany():objectCount=1  因为创建了h就调用了析构
	h.print("after construction of h");//产生了第2个输出 此时objectcount=1


	howmany h2=f(h);
	/*此时进入f的h并没有调用构造函数 却直接产生了析构函数 所以一定在某个时刻调用了构造函数否则不可能有析构函数 
begin of f
x argument inside f():objectCount=1
end of f
~howmany():objectCount=0
   */


	h.print("after call to f()");
/*在输出7之后  出现了两个析构函数 分别是h和h2的析构 所以在howmany h2=f(h)中h h2创建的过程绕过了构造函数的过程 
  
~howmany():objectCount=-1//8
~howmany():objectCount=-2//9

*/
}



输出

hommany():objectCount=1//1
after construction of h:objectCount=1//2
begin of f//3
x argument inside f():objectCount=1//4
end of f//5
~howmany():objectCount=0//6
after call to f():objectCount=0//7
~howmany():objectCount=-1//8
~howmany():objectCount=-2//9


howmany这个类会对构造和析构函数调用的次数维持一个计数

howmany这个函数 完全对象传入 对象传出 (对象返回)

在这里插入图片描述
拷贝构造

注意这里是member variable的拷贝 不是字节对字节的拷贝 是成员级别上的拷贝

在这里插入图片描述
如果有指针的拷贝指针即两个指针指向同一片内存单元

27拷贝构造二

在这里插入图片描述
在这里插入图片描述
左边的拷贝构造会出现问题 如下 所以我们希望实现的拷贝构造是右边这样的

在这里插入图片描述
在这里插入图片描述
输出结果是p1 p2的名字相同
在这里插入图片描述

输出的结果是p1p2的名字地址相同 即p1p2指向同一片内存 同时还有一个malloc错误 因为p1p2指向同一片内存 又free两次因为p1p2都要析构 所以报错

在这里插入图片描述
在这里插入图片描述
private是针对类而不是对象 所以去访问同类对象的private的东西是完全ok的

在这里插入图片描述

在这里插入图片描述

什么时候拷贝构造会发生?
隐含场景 1调用一个函数时 函数参数是对象本身(不是指针也不是引用) 就意味调用这个函数的时候 我要重新去创建一个新的person类的对象 这时候就会发生拷贝构造 因为我要用某个对象去初始化这个player
明显场景 person p1=p2

在这里插入图片描述

baby_b和baby_c用baby_a构造 等号和括号是一样的 都是初始化 这是明显的拷贝构造的场景

Person baby_c(baby_a)//这是初始化

在这里插入图片描述

在这里插入图片描述

Person p=f()
{  
  Person ip;
  return ip;
  

}


int main(){
    Person p=f()//拷贝构造 一定会有新的对象构造出来 因为f返回的是一个person 的对象 
    //可能会发生两种情况 1 Person p=ip  2 Person@tmp=f(); Person p=@tmp;
    return 0;
    
 }
123456789101112131415

在这里插入图片描述
编译器会把不必要的拷贝优化出去 optimaze·out

在这里插入图片描述
其实本质就是拿who 构造外面这个对象 所以在第二种方法中就会一步到位优化成无需拷贝构造

在这里插入图片描述
任何对象只能被初始化一次 做完之后再对它做其他动作就是assiment assiment可以多次

person p=p1//initialization
p1=p2//assiment

在这里插入图片描述
用string 可以不用拷贝构造 以为string实际上就是一个类

c++尽量用string而不是char*

在这里插入图片描述

copy ctor :拷贝构造

建议 :一旦写了一个类就必须给他三个函数default constructor ;virtual constructor ;copy constructor

28静态对象

在这里插入图片描述
static 1 持久存储(在哪) 2访问收局限(谁能看见你)

c中static的本地变量就是全局变量 因为持久存储
一个全局变量是static 这个全局变量就只在.c文件里面有效

在这里插入图片描述
deprecated 过时的
static local variables 持久存储
static 成员变量 在所有对象内共享
static 成员函数 在所有对象内共享只能访问静态对象和函数

int g_global 全局变量可以通过extern在另一个单元访问 如在 file2
static int s_global 只能file1使用 即使使用extern也不可以
static void hidden 在file2也不能被访问

就算编译阶段可以通过 但是了link阶段无法通过

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

空间在全局数据区 编译或链接的时候分配空间
全局变量的构造函数的执行什么时候做:程序一运行的时候但是在main函数之前
所以main就不是我们第一个被调用的函数了 真正程序跑的第一条代码根本不是main函数
只是程序员所以能看见的所能写的第一条代码时main函数
程序要结束的时候 对应的析构会执行

在这里插入图片描述
如果一个程序有多个点cpp文件 每个文件都会有一个全局变量
每个文件都有全局变量 这些全局变量谁先初始化谁后初始化 是没有规定规矩的 设置同一个编译器这次编译和下次编译都不一样 这样有依赖的全局变量不能被保证初始化顺序(依赖指的是某个变量要由另一个变量初始化 )

所以把有依赖的全局变量放在一个文件里

29静态成员

persistent:全局的(含有静态的本地) malloc的东西
在c++里面static不实现hidden 只实现persistent 在一个类中一个变量不会因为对象的不同而改变 即不依赖对象 所以static member 是class-wide 整个类的东西

在这里插入图片描述

在这里插入图片描述
若写成static int i会编译错误显示找不到i
若去掉static编译通过 输出b.print()的结果0 因为没有找到i

静态的成员变量实际在全局 但是写在class内的都是declaration不是definition
在这里插入图片描述
如写extern int i是声明不是定义 只是告诉编译器某个地方有个叫i的东西 但是我不知在哪里 到时候link会帮我找出来

所以如果你在class写了某个static 的成员变量 相当于extern 的效果 所以应该在.cpp内加int A::i否则只是声明 没有定义 不能是static int A::i 因为类的静态成员可能在外部被访问 不是只在点cpp被访问

在这里插入图片描述
如图 这样输出结果是10 因为静态的成员变量实际上是全局的 只有那一个 所以b.pritnt就是被a改变的那个i

#include <iostream>
using namespace std;
class A
{
public:
    A() { i = 0; }
    void print() { cout << i << endl; }
    void set(int ii) { i = ii; }
    static void say(int ii) { cout << ii << " " << i << endl; }

private:
    static int i;
};
int A::i;
int main()
{
    A a, b;
    a.set(10);
    b.print();

    a.say(0);
    A::say(0);
    return 0;
}

在这里插入图片描述

在这里插入图片描述报错 因为

initialization只能对非静态的成员初始化 不能对静态成员初始化

所以 A():i(0){} 不行 静态成员只能在定义的地方被初始化 即int A::i=20;

在这里插入图片描述
即使A::i是全局的 到那时还是不能直接cout A::i 还是会报错在这里插入图片描述

c++内所有函数都是全局的
调用静态函数的方法 没有建立这个类的对象之前也可以访问调用这个函数

 A a;
 a.say(0);
 A::say(0);
123

在这里插入图片描述
在这里插入图片描述
报错 静态的函数只能调用静态的成员变量 因为静态的成员函数是没有this的 因为this表达的是调用这个函数的那个对象 this是个hidden private 因为可以通过A::say()调用,里面没有一个对象 所以会报错

在这里插入图片描述
改成this->i 也不行 虽然i是静态的
在这里插入图片描述
因为this表达的是调用这个函数的那个对象 this是个hidden private 因为可以通过A::say()调用 所以这里面没有一个对象 所以会报错

30运算符重载基本规则(copy assignment operator)

在这里插入图片描述
在这里插入图片描述
在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。
假设b=2,c=7,d=5,
a1=(++b,c–,d+3);
a2=++b,c–,d+3;
对于第一行代码,有三个表达式,用逗号分开,所以最终的值应该是最后一个表达式的值,也就是d+3,为8,所以a1=8。
对于第二行代码,那么也是有三个表达式,这时的三个表达式为a2=++b、c–、d+3,(这是因为 赋值运算符比逗号运算符优先级高)所以最终表达式的值虽然也为8,但a2=3。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
如果是成员函数的话 this是他的第一个参数 这是隐藏默认的
所以+再给一个that变量即可

在这里插入图片描述

在这里插入图片描述

x+y//编译器发现加号左边是个interger 所以运算符左边的算子叫做receiver
这个加可能有Interger加 float加 所以取决于左边的receiver的类型来觉得怎么加
因为x是interger 所以就是interger加

z=x+y//用的overload的加
z=x+3//x是integer加 所以会把3这个int型的数变interger 再来加
z=3+y//3是int 所以用整数的加来加 y是interger 所以他需要interger这个类有个手段把interger变成int 但是interger没有 所以编译不通过

在这里插入图片描述
在这里插入图片描述

如果作为全局函数 而不是成员函数 就需要把左边右边的两个算子写上去

在这里插入图片描述
两个参数上都可以做类型转换
在这里插入图片描述

在这里插入图片描述
以上转换都可以 z=3+y//在全局函数内可以 因为当他发现用3 int加没法做的时候 就会把3变成interger来做 因为全局函数两个参数上都可以做类型转换 而成员函数要根据左边算子的类型来加 且看右边算子能不能自动变成左边算子的类如 z=3+3.5 不行因为float不能自动转变成int 必须强制类型转换 (int) z=3.5+3 可以 因为int可以自动变float

在这里插入图片描述
单目的 以及= ()[] -> ->* 31
做成成员函数
所有其他的二元运算符做成非成员的

31运算符重载-原型

在这里插入图片描述
对于参数传递
1传进去一定是引用
2若运算符会修改算子 就不能传const进去 不会修改算子的必须传const
+= -= boolean 会修改算子

3如果是成员函数 this是加在后面的const 全局函数一个加或者两个都加

在这里插入图片描述

返回值取决于你是对自己做了修改还是 制作了一个新的对象 制造出来的新对象是不是可以继续做左值

比如加法就是制造一个新的东西来 a+b=6不可以 所以他一定是const的对象
赋值来说a=6 实际上是修改了自己 所以函数后面不能有const 返回的就是reference 还可以做左值

在这里插入图片描述

++a 返回的是当时的结果 所以返回的是对象 返回a的reference 且前面有const 防止++a做左值
a++=6是不行的

a++ 要返回的是a以前的结果 而a++执行后已经不是a以前的那个结果了

在这里插入图片描述

Integer old(*this)//拷贝构造 用一个对象制造一个新的对象 ++a的调用
++(*this)//第一个++函数定义第二个++函数 第一个加加是++a的调用 第二个加加是a++的调用

在这里插入图片描述

在这里插入图片描述
关系运算符 默认this是左算子

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

32运算符重载 赋值

在这里插入图片描述
第一行调用拷贝构造函数
第二行调用赋值函数 如果你没对赋值函数重载 就调用系统默认的

#include <iostream>
using namespace std;
class Fi
{
public:
    Fi()
    {
    }
};
class Fee
{
public:
    Fee(int) {}
    Fee(const Fi &) {}
};
int main()
{
    Fee fee = 1; //Fee(int)
    Fi fi;
    Fee fum = fi; //Fee(Fi)
    fum = fi;
}

在这里插入图片描述
Fee fee=1//Fee(int)
Fi fi //default constructor 构造出来
Fee fum=fi//Fee(Fi)
fum=fi

在这里插入图片描述系统给你的=是memberwise 而不是bitwise
在这里插入图片描述
自己构造赋值函数时候 应该是个成员函数 对自己做赋值然后返回自己

在这里插入图片描述
如果自己不等于那个that 做赋值
如果自己就是那个that 就不做赋值
什么情况下拿自己等了一遍自己是有坏处的 ?如下图

如下图

如果此时that就是this delete p后p和that是同个东西 that.p不存在 不指向原来那片空间
所以strcpy(p,that.p)无法实现

所以重载=时 一定要有this!=rhs的判断
在这里插入图片描述

赋值重载 如果类里面有动态分配内存的话写,如果里面没有动态分配内存没有指针全都是成员对象 可以不写 可以用系统的
如果想防止系统做的行为不正确 可以声明为private 但是代价很大 相当于这个类的对象不能被赋值

33运算符重载—类型转换

我们希望一些类的作用是用来表达一些值的
value class:看起来像基本元素类型 被函数传进来传出去 运算符需要被重载(如分数 的加法乘法) 这个通常可以被转化为其他类型

在这里插入图片描述

string abc("abc")
PathName  xyz(abc)// 简单构造函数的调用 ok
xyz=abc //
OK 先把abc用构造函数先做成一个pathname  
然后pathname和xyz做一个 operator assiment 
(这里是default assiment 因为成员是另外一个对象不是指针 ) 
他会递归的调用string的perator assiment  所以做两个string类的assiment是ok的
1234567
#include <iostream>
using namespace std;
class One
{
public:
    One() {}
};
class Two
{
public:
    Two(const One &) {}
};
void f(Two) {}
int main()
{
    One one;
    f(one); //Wants a Two ,has a One
}

在这里插入图片描述

f想要一个two 确给了一个one 所以编译器会先用这个one去调用two的构造函数 构造一个two给f 所以是可以发生的

在这里插入图片描述

explicit 显示的 告诉编译器我这个构造函数只能做构造函数 不能自动类型转化

在这里插入图片描述

f(Two(one)) 用two的构造函数构造一个新的two的对象出来 然后交给f

在这里插入图片描述

一个A类里面的operator double()是用来把A类的对象变成double的

在这里插入图片描述

以下为自动转换 从窄的到宽的 会自动转 (即左边类型的变量可以赋给右边类型的变量)
在这里插入图片描述
T给T& 初始化时是绑定 赋值时是operator assiment
T&给T 就是赋值
T给void viod*就是个指针但是不特定指向任何东西 我原来那那块东西当T看 但是变成void的我就不拿他当任何东西来看 但是那块东西本身没有变化

T的对象可以变C的对象的情况
1 C类有个构造函数 他拿T可以做出新的对象 就可以把T转成C
2 T类定义了一个operator C()

但是当以上两者都可以时 若没有在构造函数前面加explicit时让其不能自动转换 这样就会报错 因为编译器不知道该用哪一个转化 如下图

在这里插入图片描述

所以解决办法是 在这里插入图片描述
在Orange(Apple)前加explicit

#include <iostream>
using namespace std;

class Orange;
class Apple
{
public:
    operator Orange() const; //Convert Apple to Orange
};
class Orange
{
public:
    explicit Orange(Apple) //Convert Apple to Orange
};
void f(Orange) {}

int main()
{
    Appple a;
}

要不要用类型转换函数呢 一般来说 不要用 因为自动做的事情你一般不知道
在这里插入图片描述

34模板一

在这里插入图片描述
在这里插入图片描述

把他做成函数模板 不是模板函数(sort 等等可以处理int float等等类型的排序) 模板函数(重点是函数)是函数模板(重点是模板)的实例

在这里插入图片描述

在这里插入图片描述
模板就是规定我要做一个这样的函数 怎么做 相当于告诉编译器 编译器会帮你做
模板其实是declaration 不是definition

在这里插入图片描述用了模板就不用类型转换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

把int变成complex只有一种方法 如果complex的构造函数是用int作为输入的 且不是explicit

vector的函数每一个都是函数模板 类模板的每一个函数都是函数模板 所以要记得加

在这里插入图片描述

在这里插入图片描述

arr是T类型的 遇见swap的时候 是交换T类型的 但是编译器并不会在这是造出T类型的交换 这里只是声明不是定义
并且在arr[j]<arr[j-1]处 要求T类型要实现<这个运算符的重载 否则sort无法完成排序
所以说sort用了operator<

在这里插入图片描述

在这里插入图片描述

Vector<Vector<double*> > > >// 有个vector每个单元都是vector vector每个单元都是一个double的指针 小心两个大于号连起来 会被识别成右移符号 所以需要有空格
Vector<int(*)(Vector&,int )>
一个vector里面的成员是函数指针(看<>部分) 返回的是int 他的参数表是两项 1是引用 2是int

在这里插入图片描述
在这里插入图片描述
不是模板的继承 而是模板中出现了继承的东西

36异常基本概念

在这里插入图片描述

在这里插入图片描述
读个文件的五个步骤可能会出现各种各样的问题 每一步都可能存在问题和危机

判断每一步是否会异常的动作
在这里插入图片描述
try就是尝试的五个步骤 如果捕捉到某个步骤异常 就做xxx在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
exception的好处是把业务逻辑和错误处理分的很清楚
如try 五句话 catch五部分

37异常的抛出和捕捉

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果越界的话 怎么办
1 返回一个随机的内存对象 不能接受 因为你可能会写到别人的内存地址上
2返回一个特殊的错误值 表达这是一个错误 不是好办法 因为错误值可能与后续的操作数相加减
3 exit 退出吧
4 assert 但是也不合适 因为assert表达的是代码的错误
所以综上用exception
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以一般扔出的是一个类里面的对象
在堆里:有且仅有new出来的东西
全局数据区里:全局变量 静态本地变量 静态成员变量
在堆栈里:本地变量 函数内部产生的对象

index这个对象在堆栈里 因为他是函数内部的变量

在这里插入图片描述
先看throw所在的大括号是什么 发现是if语句 所以if之后的语句不会被执行

int i=v[42] 相当于throw 然后带着这个对象离开这个函数

在这里插入图片描述
一般异常发生了往下走 不会再回去了

在这里插入图片描述
catch里面有throw可能是因为处理的层级不够 我可能可以做些小调整但是还需要更高的层次来帮忙

在这里插入图片描述
… 代表万能捕捉器 表示所有异常

在这里插入图片描述
一旦有异常发现就会沿着调用的链条一直找到try和匹配catch 的地方 然后事情在那里得到处理

exception常用于输入输出

在这里插入图片描述
如果发生问题用throw 这个语句产生异常 这个控制就会回到能控制处理这个异常的第一个部分 回去是随着调用的链和堆栈回去的 堆栈内的东西被catch后最终会被恰当的销毁

38异常语句

在这里插入图片描述
在这里插入图片描述
… 是代表所有的异常 但是拿不到对象 最好不要用
在这里插入图片描述
在所有catch里面先做1 在做2 在做3
或者针对每一条catch 做1 2 3
在这里插入图片描述
在这里插入图片描述
先看第一个catch里面是不是exact 不是
然后能不能符合base device conversion 不符合
最后是不是ellipses 不是
所以看第二个match
是不是exact 不是
然后能不能符合base device conversion 符合 所以走这个

每一个catch都按顺序按照那三个原则看能不能被匹配

在这里插入图片描述

void abc(int a):throw(MathErr){
... //告诉别的程序说 运行时刻最多只会抛出圆括号里面的那些类的异常 异常可能发生不是一定发生 发生了也只会出现()内的异常  这是限制abc
}
123

在这里插入图片描述
在这里插入图片描述
c中用malloc分内存,不够是会返回null c++用new分内存 不够会返回bad_alloc()的异常

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

构造函数出错了 抛异常 这样这个对象构造没有完成 析构是不会被调用的 如果在构造函数抛异常 别人无法拿到这个对象

new是先分配内存 先有内存然后执行构造函数 吧这个内存地址交给构造函数 于是构造函数去构造他

但是构造函数抛了异常 构造无法形成 所以p不存在 p不知道在哪 所以这是内存垃圾

所以解决办法:在构造函数加上 delete this
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
如果是new出来的 *p 一定要记得delete p

在这里插入图片描述
我们倾向于抛的是堆栈里的对象

39流的概念

在这里插入图片描述
文件二进制和文本文件

在这里插入图片描述
inserters 把一个对象插入到一个输出流的运算符<<
extractors >>把一个对象插入到一个输入流的运算符

在这里插入图片描述

流是一维单方向和文件不一样 文件可以在里面任意流动可以在任意地方读和写

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
scanf printf cin cout都是对文本文件操作的 所有的输入输出都是在做解析
二进制字符转换成了我们看见的ASCII码 这叫parse 解析
文本文件都要经过 输入其实是解析 输出其实是格式化

二进制文件 人是看不懂的 是直接对其读和写

40流的运算符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
自定义的>> 返回的要是 isream&
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

规定输出的格式 endl是manipulators
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
set是变为1 reset是变为0

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

41stl简述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
sets 集合没有重复的是无序的 maps映射

在这里插入图片描述

在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> x;
    for (int a = 0; a < 1000; a++)
    {
        x.push_back(a);
    }
    vector<int>::iterator p;
    for (p = x.begin(); p < x.end(); p++)
    {
        cout << *p << " ";
    }
    return 0;
}

在这里插入图片描述
在这里插入图片描述
v.swap(v2)交换的是两个vector的值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-06 23:57:47  更:2021-07-06 23:58:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 4:34:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码