侯捷C++面向对象高级编程(上)笔记

培养正规的、大气的编程习惯

头文件声明

在这里插入图片描述

如果没有定义就定义一个complex。如果定义过了就不再进入头文件的定义,防止多次引用一个头文件这正是我们想要的。

模版T

在这里插入图片描述
通过模版T来指定类型
在这里插入图片描述

inline函数

类里面定义的函数就是inline函数
不在本体中定义的可以加一个inline
在这里插入图片描述

访问级别

所有的数据都应该放在private,有些函数只打算函数内使用设为private
在这里插入图片描述

构造函数

创建一个对象,创建一个东西
函数名称和类名相同
可以有默认值
构造函数其实就是代表创建这种东西(就是这个类)所以没有必要有返回类型
在这里插入图片描述
利用初始列初始化,
re =r
im = i
为什么要在这里初始化呢?
与在函数里面初始化的区别是:
第一阶段是初始化初值列
第二阶段是大括号里面的赋值

如果在第二阶段大括号里面赋值放弃了第一阶段的初始化,效率变差

不带指针的类多半不需要析构函数

多种构造函数(重载)

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

构造函数放在private里面

在这里插入图片描述
private不被外界调用,下面的调用会报错
那放在private有什么用呢?
设计模式中有一个Singleton,就把构造函数放在private里面
在这里插入图片描述
Singleton意思为为单体
里面自己准备了自己
在这里插入图片描述
只有通过这个函数才能获取自己
告诉我们确实有这种写法把构造函数放在private里面。

常量成员函数

对class里面有不改变数据和改变数据的,
只是拿出来,
在这里插入图片描述
前面加上const,表示我这个对象是不可以改的
我们在底下应用的时候不加const不会报错,但是我们要写出大气的代码,要考虑周全
在这里插入图片描述
如果没有const就会报错
在这里插入图片描述

参数传递by value 或by 引用

在这里插入图片描述
by value就是整包都传过去,value多大就放过去 (栈)
尽量传引用,过去C中都是指针(4字节很快)
**C++我有一个指针但更漂亮–引用 **

尽量所有的参数传递都传引用
如果是字符呢? 1个字节 但是大范围都是引用
如果不希望对方改 加cosnt。

返回值by 引用

在这里插入图片描述
尽量返回值为引用,后面再谈。

友元

在这里插入图片描述
这个函数可以直接拿private里面的内容,因为是friend。

朋友直接拿数据会快一点相比函数

朋友可以打破封装

同一个class中的各个对象互为友元

看似打破了封装,其实是成立的。
在这里插入图片描述

小结:

  • 数据一定放在private里面

  • 参数尽可能以reference来传,要不要const视情况而定

  • 返回值尽量以reference来传。首先考虑我用reference可不可以

  • 在类的本体里的函数应该加const的就应该加,否则设计者想用的const的时候你没加会报错。

  • 构造函数有一个特殊的语法叫innegerlazationlist:尽量去用它。

操作符重载(成员函数) this

所有的成员函数里面都有一个隐藏的参数,这里是this其实虽然他没写但是他是隐藏的,
我们写成下面的this就错了,
你不能在参数列里把this写出来,但是你可以在里面用
左边的c2对应是this最终加到c2上。
在这里插入图片描述
谁调用我,谁就是那个this,,this是一个指针 。

传递者无需知道接受者是以引用接收,就像c1作为传递者 ,const compex& r作为接收者
在这里插入图片描述

操作符重载(非成员函数) this,创建临时变量

在这里插入图片描述
之前用到complex&是加到左边,那个东西是存在的
而现在是加到一个不存在的东西(临时对象),所以不可以是引用
蓝色部分是return by value
因为我们return 的是一个临时变量
在这里插入图片描述

typename():
创建临时对象
complex(); // 0,0

在这里插入图片描述
在这里插入图片描述
C++中没有作用于右边操作的语法
左边是cout
在这里插入图片描述
操作符有成员函数的写法,也有非成员函数的写法
对着cout这种特殊的只有用全局的写法,因为对于以前现有的东西像等<<这种现有的符号不要想着写为成员函数的写法

这里不可以加const在这里插入图片描述
如果加const,传进来的os不可被改变
这里也看不出来我改他啊,其实往os里面丢的时候其实在修改
每一次输出都在改变os的状态。

7.三大函数:构造拷贝、拷贝复制、析构

带指针的类

在这里插入图片描述
如果是带指针的就不能用编译器的那一套拷贝,会让指针指向同一个地方。

Big Three,三个特殊函数

下面的是我们前面介绍的构造函数:
在这里插入图片描述

(1)拷贝构造

接受自己的东西:拷贝构造
在这里插入图片描述

(2)拷贝赋值

赋值操作符重载,右边赋值还是自己这个东西:拷贝赋值:
在这里插入图片描述

(3)析构函数在这里插入图片描述

构造函数和析构函数

在这里插入图片描述
带有指针的类必须要有拷贝构造和拷贝赋值

在这里插入图片描述
下面就是浅拷贝的动作。

在这里插入图片描述
拷贝构造应该创建足够的空间存放蓝本
这两个等同,都是创建一个新东西去接收蓝本。
在这里插入图片描述
如果没有写这个
在这里插入图片描述
而是把指针给过去,那就是浅拷贝。会造成内存泄露
在这里插入图片描述
alias:别名。

拷贝赋值函数:
本来就有的两个东西,需要把原来的东西清空,分别配一个和原来一样大的空间,把数据拷贝过来

在这里插入图片描述
把s1作用到s2身上,this就是指向s2根据上面的123流程如下:
(1)先清空s2自己的m_data
(2)然后重新分配一个空间给s2
(3) 拷贝过来

另外:功力深厚才能写出来这句话,这句话一定要有:

在这里插入图片描述
如果是相同的元素赋值进来,没有这句话的话:
在这里插入图片描述
先把自己删掉,后面再进行赋值自己已经不存在了。

8.堆、栈与内存管理

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

在这里插入图片描述
先调用析构函数,后释放内存。
在这里插入图片描述

动态分分配所得的内存块:

红色为cookie 为 4 2
灰色为8
4+4
再加上conplex 8
=52
vc每一个区块都是16
pad填补后为64

64十六进制为0x40这个地方给你了进1所以是0x41,如果把这个地方还给操作系统就变成0x40

在这里插入图片描述
Debug模式下会有32+4(上面的灰色空间、下面的黄色空间)
在这里插入图片描述
因为是3个complex会有4个字节记录为3;
80的16进制50,给出这块空间+1 所以是51

array delete

在这里插入图片描述

如果delect数组的时候不写[] 系统只会删除第一个,他不知道还有2和3

会造成内存泄漏。

9.复习String类的实现过程

定一个指针类型的char* 4个字节。 后面通过动态分配来提供空间
在这里插入图片描述
类里面带有指针:关注big three 3个特殊的函数

拷贝构造;拷贝赋值

传进来的数据不改变 形参加上const,拷贝构造需要一个蓝本,蓝本就是他自己 ,加上引用。
在这里插入图片描述

传出去的数据不改变 后面加上const
在这里插入图片描述
构造函数:
在这里插入图片描述
把很复杂的函数也写成inline,没关系,如果不能inline编译器自然不会去做
拷贝赋值:
从来源端到目的端
目的端是已经存在的东西,所以目的端需要把自己清掉
再分配一块够大的空间,给他重新赋值
其实我们函数名设为void 不return某种情况下OK
但是在某种连串赋值的情况下就不可以。

传出去的是一个东西 return *this,不管你接收是by value还是by reference方式接收
传出去的人
不必知道接收端是什么形式来接收,
如果你要指针或引用就看你函数的返回类型怎么写了

在这里插入图片描述

10 类模版、函数模版及其他

static 静态数据或函数
在这里插入图片描述
this可写可不写,不写编译器会帮你加上

static单独会有一个区域存放

并且静态函数没有this point
可见不能像一般的去处理

在这里插入图片描述
里面是声明static double m_rate;
外面黄色部分是:静态变量的定义,给不给数据都可以。

  • 对于static: 1.类内声明,类外初始化
  • 2.静态成员函数只能访问静态成员变量
  • 3.通过class名调用或者通过对象来调用
    調用static 函數的方式有二:
    (1) 通過object 調用
    a.set_rate(7.0);
    (2) 通過class name 調用
    Account::set_rate(5.0);

单例模式(设计模式)

前面说到的单例模式
我们写的class只希望一个对象

在private里面放一个 自己的静态A ,在没有创建A的对象的时候,他已经在一个了,我不想让外界创建A,把他的构造函数放在private里面
没有任何人能创建它了,他只有一个自己A
外界如何取得它的,通过静态函数:这个函数就是把刚刚他的自己return回去,所以getInstance是外界的唯一接口
在这里插入图片描述
通过得到的唯一的A去 获得类里面的其他函数

在这里插入图片描述
但是这个写法不是最完美的
把静态的自己放在函数里,当有用户调用到他(getInstance)他才会创建
离开这个函数后,A还在
如果没有任何人使用这个单例,这个单例就不存在
如果有人用了这个单例也就永远只有这一份。
在这里插入图片描述
cout:
在这里插入图片描述

函数模版:

在这里插入图片描述

namespace

在这里插入图片描述

11 组合与继承,设计模式与容器

复合

在这里插入图片描述

Adapter(设计模式)

A拥有B,A的所有功能都让B来做
B:deque 两端都可以进出
A:queue 一端进出
相当于我有一个很强大的东西,稍微改装一下
在这里插入图片描述
复合的空间大小:

在这里插入图片描述
A包含B:(红色编辑器帮我们加上的)
构造先B后A(B在外面先执行)
在这里插入图片描述

析构先A后B(B在括号里面后执行)
在这里插入图片描述

在这里插入图片描述

委托composition by reference

A里面有B,但是B有点虚 是一个 指针
需要右边的B才会创建而复合里面的B是一创建就有的
在这里插入图片描述
右边怎么变化都不影响左边,不影响字符串

就像编译防火墙 左边永远不会变,变的是右边

继承

子类里面会有父类的part
在这里插入图片描述

三种继承方式 public private protected
在这里插入图片描述

在这里插入图片描述

12.虚函数和多态

在这里插入图片描述
父类里面的函数,上面这些子类都可以调用
子类要不要重新定义:
(1)非虚函数:你不希望子类重新定义
虚函数重新定义才能用override(复写).

(2)虚函数:你希望子类重新定义它,并且他已经有默认定义
对于上面的error他有默认的提醒错误的消息,如果你想对于子类不想用默认的我允许你重新定义它,如果有哪一种形状出错,自然调用那一种error

(3)纯虚函数:你希望子类一定要重新定义它,你对他没有默认定义

Tempate Method(设计模式)

在这里插入图片描述

在这里插入图片描述

父类CDocument的serialize是抽象的
需要子类以后把他实体化

CMyDoc继承了CDocument类,它里面有一个seralize我暂时不想处理,希望让子类去处理它。

当子类调用OnFileOpen的时候会回到父类去调用父类的函数OnFileOpen,因为父类里面有seralize

到这里时,会运行子类里面写的serialize也就是后来让子类去完成的函数。
在这里插入图片描述

在这里插入图片描述

继承加复合下的构造和析构

在这里插入图片描述

(1)
在这里插入图片描述

#include<iostream>
#include<string>
#include<list>
using namespace std;
// Derived继承于Base,Derived里面又有一个Component
class Base{
public:
    Base()
    {
        cout << "Base的构造函数" << endl;
    }
    ~Base()
    {
        cout << "Base的析构函数" << endl;
    }
    void printBa()
    {
        cout << "Base" <<endl;
    }

};



class Component{

public:
    Component()
    {
        cout << "Component的构造函数" << endl;
    }
    ~Component()
    {
        cout << "Component的析构函数" << endl;
    }
    void print()
    {
        cout << "Component" << endl;
    }

};

class Derived : public Base{

public:
    Derived()
    {
        cout << "Derived的构造函数" << endl;
    }
    ~Derived()
    {
        cout << "Derived的析构函数" << endl;
    }
    void printDe()
    {
        abc.print();

    }

private:
    Component abc;

};

void test01()
{
    Derived c;
    c.printDe();

}

int main() {

    test01();

    return 0;

}

 

(2)
在这里插入图片描述
这种情况下构造函数和析构就很清晰了
当然是最里面的Conponent构造先调用,析构最后调用。

委托+继承(Observer设计模式)

在这里插入图片描述
在这里插入图片描述
ppt中一个大窗口看同一份东西:

在这里插入图片描述

13.委托相关设计

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值