C++:类和对象初识
C++:类和对象初识
- 前言
- 类的引入与定义
- 引入
- 定义
- 类的两种定义方法
- 1. 声明和定义全部放在类体中
- 2. 声明和定义分离式
- 类的成员变量命名规则
- 类的访问限定符及封装
- 访问限定符
- 封装
- 类的作用域与实例化
- 类的作用域
- 类实例化
- 实例化方式:
- 类对象模型
- 类对象的大小
- 存储方式
- this指针(重点)
- 引出
- 特性
- 深入理解
- 思考题?(重点中的重点)
- 解答情形1
- 解答情形2
- 原因分析
- 总结
前言
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
以我们洗衣服为例:
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
在面向对象编程(OOP)中,"类"和"对象"是最核心的概念。C++作为一门面向对象的语言,通过类和对象实现了数据抽象、封装、继承和多态等特性。理解类和对象的工作机制是掌握C++面向对象编程的关键。
类的引入与定义
引入
在C语言中,我们使用结构体(struct)来组织相关数据。C++在此基础上进行了扩展,允许结构体中不仅包含数据成员,还可以包含函数成员:
C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数。
//C++兼容C语言,同时C++中struct升级成了 类(具有类的所有特性)
struct _Stack {//成员方法void Init(int defaultCapacity = 4) {base = (int*)malloc(sizeof(int) * defaultCapacity);if (base == nullptr) {perror("malloc failed\n");return;}this->size = 0;this->capacity = defaultCapacity;}void Push() {//......}void Destroy() {free(this->base);this->base = nullptr;this->top = this->capacity;}//成员变量int* base;int top;int capacity;int size;
};
C++中结构体的名字,可以当成类名来使用。C++中的结构体具有class的所有功能(包括但不限于权限管理与this指针),只是成员的默认权限不同。
- 结构体中,
所有成员的默认访问权限是public
,结构体外可以直接访问 - C++的类中,
class所有成员的默认访问权限是private
, 不能再类外访问。
但更规范的C++做法是使用class关键字来定义类,它提供了更完善的访问控制机制。
定义
类定义的基本语法:
class className{// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
- class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
- 类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
示例:
class Clock {
private: // 访问限定符int hour;int minute;int second;public:void setTime(int h, int m, int s);void showTime() {cout << hour << ":" << minute << ":" << second << endl;}
};
类的两种定义方法
1. 声明和定义全部放在类体中
例如该类:
class Clock {
private: // 访问限定符int hour;int minute;int second;public:void showTime() {cout << hour << ":" << minute << ":" << second << endl;}
};
- 声明和定义全部放在类体中,需注意:成员函数如果在类体中定义,编译器可能会将其当成内联函数处理。(相当于在函数前加上了
inline
关键字,建议编译器使其称为内联函数)
2. 声明和定义分离式
//Stack.h
class Stack {
public:void Init(int defaultCapacity = 4);//在类内定义的函数,会直接建议编译器让该函数称为内联函数,void Push() { //类内定义的函数,不管加不加 inline ,都相当于加上了 inline //.......此处省略}void Pop() {//.......}
private:int* base;int top;int capacity;
};
//Stack.cpp
//类的声明和定义分离,需要在函数名前面,加上类的作用域限定
void Stack:: Init(int defaultCapacity) { //缺省参数一般在 函数声明 给出base = (int*)malloc(sizeof(int) * defaultCapacity);capacity = defaultCapacity;top = 0;
}
需要注意的是:
声明定义分离式
,如果函数有默认参数,一般要在函数声明处给出类的默认参数
一般情况下,更期望采用第二种方式, 因为我们并不希望所有的函数都称为内联函数。
类的成员变量命名规则
我们看该类:
class Clock {
private: // 访问限定符int hour;int minute;int second;public:void setTime(int hour, int minute, int second){// 这里的hour到底是成员变量,还是函数形参?hour = hour;}
};
我们的疑问如注释中所写,为了避免这样的矛盾,我们通常这样定义类的成员变量。
private: // 访问限定符int _hour;int _minute;int _second;
public:void setTime(int hour, int minute, int second){// 这里的hour到底是成员变量,还是函数形参?_hour = hour;//这样就解决了分歧,避免了二义性。}
类的访问限定符及封装
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用
访问限定符
C++通过三个访问限定符实现封装:
public
:公有成员,类内外均可访问private
:私有成员,仅类内和友元可访问protected
:保护成员,介于两者之间(继承时使用)
特点:
public
修饰的成员在类外可以直接被访问。protected
和private
修饰的成员在类外不能直接被访问(此处protected和private是类似的)。- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
- 如果后面没有访问限定符,作用域就到}即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C语言)。
- C++需要兼容C语言,所以C++中struct可以当成结构体使用。
- 另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。
- 注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家介绍。
通常建议我们不要采用C++语法中的默认权限,不管是class还是struct,我们都应该手动控制访问权限。
封装
面向对象的三大特性:封装、继承、多态
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装是指将数据和操作数据的方法进行有机结合,并对外部隐藏实现细节。其优势体现在:
- 数据保护:通过私有化成员变量防止意外修改
- 接口统一:通过公有方法提供规范的操作方式
- 实现隔离:修改内部实现不影响外部使用
示例封装:
class BankAccount {
private:double balance; // 私有数据public:// 公开接口void deposit(double amount) {if(amount > 0) balance += amount;}bool withdraw(double amount) {if(amount <= balance) {balance -= amount;return true;}return false;}double getBalance() const { return balance; }
};
类的作用域与实例化
类的作用域
类定义了一个独立的作用域:
- 成员变量/函数的作用域在整个类体内(整个类内是一个整体)
- 外部访问需通过类名::成员或对象.成员
注意点:
- 如上文所讲,成员函数在类外定义时需要指定类域
void Clock::setTime(int h, int m, int s) {// 实现代码
}
我们可以对比一下各种作用域各有什么特点。
全局域
局部域
类作用域
命名空间域(使用时需要指定)
局部域和全局域会影响变量的生命周期, 类域和命名空间域不会影响生命周期
类实例化
用类类型创建对象的过程,称为类的实例化
- 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
int main(){person._age = 100; // 编译失败:error C2059: 语法错误return 0;
}
Person类是没有空间的,只有Person类实例化出的对象才有具体的年龄。
做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
实例化方式:
Clock myClock; // 栈上分配
Clock* pClock = new Clock; // 堆上分配
new关键词我们将在后续讲解。
需要注意:
- 类声明不分配内存,实例化时才分配实际空间
- 同一类的不同对象拥有独立的成员变量存储空间
- 成员函数被所有对象共享(代码区存储)
类对象模型
类对象的大小
计算规则:
- 遵循结构体内存对齐原则
- 只计算成员变量大小(包括继承的)
- 空类大小为1字节(占位标识)
验证示例:
class Empty {};
class Data {int num; // 4字节double value; // 8字节char tag; // 1字节
};// 8 + 8 + 1 = 17 → vs下实际输出24(内存对齐)int main() {cout << sizeof(Empty) << endl;; // 输出1cout << sizeof(Data) << endl;; // 输出24
}
存储方式
类对象的存储采用分治策略:
- 成员变量:每个对象独立存储(栈区/堆区)
- 成员函数:所有对象共享代码区的一份拷贝
- 静态成员:存储在全局数据区
如图所示
这个模型在我们计算对象的大小时也有体现
:
- 对象中只存储成员变量。
- 成员函数存放在一个公共区域(成员函数不在对象内存储)
内存布局示例:
对象1: [成员变量区]
对象2: [成员变量区]
...
代码区: [成员函数]
结论:
- 一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐。
- 注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。
结构体内存对齐规则
//结构体内存对齐规则
//1. 第一个成员在与结构体偏移量为0的地址处。
//2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
//注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
//VS中默认的对齐数为8
//3. 结构体总大小为:最大对齐数(所有变量类型最大者 与 默认对齐参数 取较小的那个)的整数倍。
//4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
//体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
this指针(重点)
引出
我们先定义一个日期类
class Date{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout <<_year<< "-" <<_month << "-"<< _day <<endl;
}int main(){Date d1, d2;d1.Init(2025,1,11);d2.Init(2024, 2, 22);d1.Print();d2.Print();return 0;
}
对于上述类,有这样的一个问题:
Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
编译器隐式添加this指针参数:
// 编译器视角下的成员函数
//编译器编译后,会对成员函数进行处理,会给成员函数加上参数this, 访问变量时,使用this访问
void Init(Date* const this, int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}
void Print(Date* const this){cout <<this->_year<< "-" <<this->_month << "-"<< this->_day <<endl;
}int main(){Date d1, d2;//编译器视角下的函数调用,是编译器帮助我们传入的当前对象的地址d1.Init(&d1, 2025, 1, 11);d2.Init(&d2, 2024, 2, 22);d1.Print(&d1);d2.Print(&d2);return 0;
}
特性
- this指针的类型:
className* const
,const修饰指针本身,该指针不能被修改,也就是不能当左值。即成员函数中,不能给this指针赋值。 - 只能在“成员函数”的内部使用
- this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。正因如此,上文计算对象大小的时候并没有计算this指针。
- this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
- this指针在函数内部是要反复调用的, vs的编译器对this指针传递做了优化,对象地址放在ecx寄存器中,exc中存储this指针的值
- this指针是函数的形参,因此this指针存放在内存的栈区中
深入理解
思考题?(重点中的重点)
有如下类和代码,思考?
class TestThis {
public:void Print() {cout << "Print" << endl;}void PrintA() {cout << _A << endl;}
private:int _A;
};
void Test_This_1() {TestThis* p = nullptr;p->Print();
}
void Test_This_2() {TestThis* p = nullptr;p->PrintA();
}
int main(){Test_This_1();//Test_This_2();return 0;
}
思考两个函数调用的结果分别是什么?
1.编译时报错 2. 运行时崩溃 3. 正常运行
我们依次调用来看:
解答情形1
我们可以看到,中断打印Print, 并且提示:进程已退出,代码为0
,0代表正常返回,可以看到,第一种情况的结果是:正常运行。
解答情形2
观察两张图可看到,图一,光标一直在闪动,图二,程序结束时,退出代码为**-1073741819**,光标一直在闪动且退出代码为负数,显然是运行时崩溃。
原因分析
class TestThis {
public:void Print() {cout << Print() << endl;}void PrintA() {cout << _A << endl;}
private:int _A;
};
先看该类,挺简单的。两个成员函数:
Print()
,打印字符串“Print”
PrintA()
,打印成员变量_A的值
再看两个调用:
void Test_This_1() {TestThis* p = nullptr;p->Print();
}
void Test_This_2() {TestThis* p = nullptr;p->PrintA();
}
说白了讲,p是TestThis对象的空指针,通过指针p,分别调用
Print()
和PrintA()
函数
class TestThis {
public:void Print() {//this指针为空,但函数内没有对this指针解引用cout << Print() << endl;}void PrintA() {//this指针为空,但函数内访问_A,本质是this->_A//成员变量在对象内,因此发生了this指针的解引用。cout << _A << endl;}
private:int _A;
};
void Test_This_1() {TestThis* p = nullptr;//表示this指针为空p->Print();
}
void Test_This_2() {TestThis* p = nullptr;//表示this指针为空p->PrintA();
}
两种情形下,this指针都是空的。
p->Print();
,p调用Print, 不会发生解引用。因为,由上文得,Print的地址并不在对象中,p会作为实参传递给this指针,并没有发生空指针的解引用。p->PrintA();
,p调用PrintA, 不会发生解引用。但PrintA()
函数内,有cout << _A << endl;
,本质上是cout << this->_A << endl;
,变量_A
存储在对象内,因此需要去对象中找,也就发生了对象指针的解引用。此时对象指针为空,那么对空指针解引用,也就发生了运行时崩溃。
总结
- 类与对象关系:类是蓝图,对象是实体
- 访问控制:通过public/private/protected实现封装
- 存储模型:对象独立存储数据,共享函数代码
- this机制:隐式指针实现对象自治
- 设计原则:高内聚低耦合,合理使用访问限定符
理解类和对象的工作机制是掌握C++面向对象编程的基础,后续的继承、多态等特性都是建立在此基础之上的深入扩展。正确使用类和对象可以有效提高代码的可维护性和复用性。
今天的分享到此结束了,各位大佬多多支持。
一键三连,好运连连!
相关文章:

C++:类和对象初识
C:类和对象初识 前言类的引入与定义引入定义类的两种定义方法1. 声明和定义全部放在类体中2. 声明和定义分离式 类的成员变量命名规则 类的访问限定符及封装访问限定符封装 类的作用域与实例化类的作用域类实例化实例化方式: 类对象模型类对象的大小存储…...

官网下载Redis指南
1.访问官网 https://redis.io/downloads/#stack 2.点击redis图标 拉到下面点击download 在新页面拉到最下面,点击install from source 找到需要的大版本后,点击releases page 最后点击下载需要的版本号即可...

活动预告 |【Part1】 Azure 在线技术公开课:迁移和保护 Windows Server 和 SQL Server 工作负载
课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft 云技术的了解。参加我们举办的“迁移和保护 Windows Server 和 SQL Server 工作负载”活动,了解 Azure 如何为将工作负…...

【Linux系统编程】五、进程创建 -- fork()
文章目录 前言Ⅰ. 重温fork函数一、fork()的概念二、如何理解fork()有两个返回值 Ⅱ.fork的常规用法Ⅲ. fork调用失败的原因Ⅳ. 写时拷贝为什么存在写时拷贝❓❓❓ 前言 现阶段我们知道进程创建有如下两种方式,其实包括在以后的学习中这两种方式也是最常见的&#…...
深入解析 STM32 GPIO:结构、配置与应用实践
理解 GPIO 的工作原理和配置方法是掌握 STM32 开发的基础,后续的外设(如定时器、ADC、通信接口)都依赖于 GPIO 的正确配置。 目录 一、GPIO 的基本概念 二、GPIO 的主要功能 三、GPIO 的内部结构 四、GPIO 的工作模式 1. 输入模式 2. 输出模式 3. 复用功能模式 4. 模…...

深入探究 C++17 std::is_invocable
文章目录 一、引言二、std::is_invocable 概述代码示例输出结果 三、std::is_invocable 的工作原理简化实现示例 四、std::is_invocable 的相关变体1. std::is_invocable_r2. std::is_nothrow_invocable 和 std::is_nothrow_invocable_r 五、使用场景1. 模板元编程2. 泛型算法 …...
Vmware网络模式
一、Vmware虚拟网络 Vmware共支持创建20个虚拟网络,相当于现实生活的交换机,名称vmnet0-vmnet19 没创建一个虚拟网络。对应在物理机会自动生成相应的虚拟网卡 该虚拟网卡用于和对应的虚拟网络中的虚拟机通信 二、虚拟网络的工作模式 1、nat模式 …...

神经辐射场(NeRF):从2D图像到3D场景的革命性重建
神经辐射场(NeRF):从2D图像到3D场景的革命性重建 引言 在计算机视觉和图形学领域,如何从有限的2D图像中高效且准确地重建真实的3D场景,一直是一个重要的研究方向。传统的3D重建方法,如多视角几何、点云重建…...

深入解析AI技术原理
序言 在当今数字化时代,人工智能(AI)已经成为科技领域最炙手可热的话题之一。从智能家居到自动驾驶汽车,从医疗诊断到金融风险预测,AI的应用无处不在。然而,对于许多人来说,AI背后的技术原理仍然充满了神秘色彩。本文将深入探讨AI的核心技术原理,从基础理论到前…...
PDF 2.0 的新特性
近来闲来无事,就想着把PDF的新标准研究研究,略有所得,和大家分享一下。 PDF 2.0的主要新特性包括更高级的加密算法、改进的数字签名和权限管理机制、增强了对非罗马字符的支持,以及扩展了标签架构和3D建模语言“PRC”的支…...

Matlab机械手碰撞检测应用
本文包含三个部分: Matlab碰撞检测的实现URDF文件的制作机械手STL文件添加夹爪 一.Matlab碰撞检测的实现 首先上代码 %% 检测在结构环境中机器人是否与物体之间发生碰撞情况,如何避免? % https://www.mathworks.com/help/robotics/ug/che…...

(root) Additional property include:is not allowed
参考:执行docker compose命令出现 Additional property include is not allowed_(root) additional property include is not allowed-CSDN博客 原因是docker-compose的版本太低,下载最新的替换即可。 第一次2.6.x版本改成了2.19.x不够高,所…...
react 18父子组件通信
在React 18中,父子组件之间的通信方式与之前的版本基本相同,主要可以通过以下几种方式实现: 1. Props(属性) 父组件向子组件传递数据: 父组件通过属性(props)向子组件传递数据&am…...
FastReport 加载Load(Stream) 模板内包含换行符不能展示
如下代码 当以FastReport 载入streams时 当模板内包含换行符时会导致不能正常生成pdf System.Xml.XmlDocument newFrxXml new System.Xml.XmlDocument(); newFrxXml.Load(fileName);FastReport.Report report new FastReport.Report();using (var memStream new MemoryStre…...
Maven 中常用的 scope 类型及其解析
在 Maven 中,scope 属性用于指定依赖项的可见性及其在构建生命周期中的用途。不同的 scope 类型能够影响依赖项的编译和运行阶段。以下是 Maven 中常用的 scope 类型及其解析: compile(默认值): 这是默认的作用域。如果…...
vue3:点击子组件进行父子通信
问: 子组件怎么和爷爷组件通信 回答: 在Vue 3中,子组件和爷爷组件之间的通信可以通过事件冒泡和状态管理来实现。你可以使用Vue的事件系统来传递事件,或者使用全局状态管理库如Vuex或Pinia。以下是一个使用事件冒泡的示例&…...

Composo:企业级AI应用的质量守门员
在当今快速发展的科技世界中,人工智能(AI)的应用已渗透到各行各业。然而,随着AI技术的普及,如何确保其可靠性和一致性成为了企业面临的一大挑战。Composo作为一家致力于为企业提供精准AI评估服务的初创公司,通过无代码和API双模式,帮助企业监测大型语言模型(LLM)驱动的…...
Jackson扁平化处理对象
POJO对象 Data public class People {private PeopleInfo peopleInfo;private List<String> peopleIds;private Map<String, String> peopleMap;Datapublic static class PeopleInfo {private String name;private String address;} }JSON序列化处理 直接将对象进…...
Java即时编译器(JIT)的原理及在美团的实践经验
基本功 | Java即时编译器原理解析及实践 - 美团技术团队 这篇文章由美团AI平台/搜索与NLP部的珩智、昊天、薛超撰写,深入介绍了Java即时编译器(JIT)的原理及在美团的实践经验。 Java执行过程与即时编译器概述 Java执行过程:Java…...

使用 Ollama 在 Windows 环境部署 DeepSeek 大模型实战指南
文章目录 前言Ollama核心特性 实战步骤安装 Ollama验证安装结果部署 DeepSeek 模型拉取模型启动模型 交互体验命令行对话调用 REST API 总结个人简介 前言 近年来,大语言模型(LLM)的应用逐渐成为技术热点,而 DeepSeek 作为国产开…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...