把以前的笔记搬上来一下 根据浙大翁恺老师视频整理 https://www.bilibili.com/video/BV1yQ4y1A7ts?p=2
01第一个c++程序
02什么是对象


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




设计就是找出思路的过程 实现就是写代码的过程 oo思想关注的是东西是数据而不是过程操作
03面向对象基本原理



object实体 class是种概念不是实体

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



class creator 自己造的类 可以修改类里面的数据 但是client programmers可以调用类但是不能直接接触类中的数据 而是通过接口

三大特性:封装 继承 多态性
04自动售票机例子



按照过程模拟售票机 不合理 应该关注其内部有什么东西




::”类作用域操作符。“::”指明了成员函数所属的类。如:M::f(s)就表示f(s)是类M的成员函数。
::a++ 前面没有类名 表示是全局的





源代码.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 记录这块内存的地址 这个内存有多大

假设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)

这里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)是不合法的
17函数重载与默认参数

函数重载就是 同名 参数列表不同 (类型 个数等等)

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

default argument是发生在编译时刻 尽量不要使用default value
18内联函数
overhead 额外的开销


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


左边是函数调用 右边是内联函数 二者的汇编对比

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


本文详细介绍了C++的面向对象编程概念,包括对象、类、封装、继承、多态等核心概念。讲解了构造函数、析构函数、成员变量、访问控制、函数重载、内联函数、拷贝构造、静态成员、运算符重载、异常处理、模板和STL的基础知识,并探讨了C++中的内存管理和对象生命周期。
4438

被折叠的 条评论
为什么被折叠?



