C++初识类和对象

前言

上一期我们介绍了一些C++入门的基础知识,本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装!

本期内容介绍

面向过程和面向对象

类的引入

类的定义

类的访问限定符和封装

类的作用域

类的实例化

类对象模型

this指针

一、面向过程和面向对象

面向过程(C语言)关注的是过程,即分析出求解问题的步骤,通过函数调用逐步解决问题。而面向对象(C++)关注的是对象,即解决的事情被分成不同的对象,各个对象配合完成

以前我也不怎么理解面向对象和面向过程!后来看到了很多例子后逐渐有了理解!我来举一个我以前理解最好的例子 --- 洗衣服。

面向过程:用面向过程来洗衣服的步骤:找盆 ---> 接水 ---> 放洗衣液 ---> 放衣服 ---> 手搓 ---> 换水 ---> 再洗 ---> 换水 ---> 拧干 ---> 晾晒。你得关注每一步的过程

面想对象:用面向对象来洗衣服的步骤:人、衣服、洗衣机、洗衣液。整个过程就是人将衣服洗衣液,放到洗衣机中启动洗衣机,洗衣机洗好了会烘干!具体的洗衣服和烘干过程你根本不用关心,这是洗衣机的事情!

当然还有其他同类的例子,例如把大象装到冰箱里面!

二、类的引入

C语言的struct只能定义变量,在C++中不仅可以定义变量,而且可以定义函数。例如我们以前C语言中玩的栈,就是只能在结构中定义变量,而C++中可以定义函数!

C语言版本:

typedef int STDataType;
struct Stack
{STDataType* a;int top;int capacity;
};

他的方法只能在外面!而C++就可以在里面!

C++版本:

#include <iostream>typedef int STDataType;
struct Stack
{STDataType* _a;int _top;int _capacity;void Init(int capacity = 4){_a = (STDataType*)malloc(sizeof(STDataType) * capacity);if (_a == nullptr){perror("malloc failed");exit(-1);}_capacity = capacity;_top = 0;}//...
};

上述操作可以,但C++中更喜欢用class来替代struct

三、类的定义

class ClassName
{//成员变量和成员方法(函数)
};//注意封号

class是C++中定义类的关键字ClassName 是类的名字 {}中为是类的主体。和struct一样结束的 ; 不能省略

类体中(即{}中)的内容被称为类的成员,成员被分为变量和函数。成员变量又被称为成员的属性,用来描述该对象的特征成员函数又被成为成员方法,是描述类的行为的!

类的两种定义方式

1、声明和定义全部放在类体中,需要注意的是:成员函数在类体中默认是内联的!

class Student
{
public://成员方法void sleep(){cout << _name << "正在sleep()..." << endl;}private://成员属性char* _name;char* _sex;int _age;
};

当然这里用struct也可以定义类!

2、声明和定义分开即声明放在.h,定义在.cpp中时,在定义的成员函数名前需要加类名和作用域限定符::,来指定是哪个域的!

小tips: 我们一般建议使用第二种

成员变量的命名规则

我一般习惯时在成员属性的成员的前面加一个下划线,这个的作用主要是区分形参和成员属性的。具体怎么加,看你的想法,以及需求,只要能分开都可以!但也要符合我们以前C语言介绍过的标识符命名规则!如下就是C语言的表示符命名规则:

  1. 标识符只能由字母、数字和下划线组成。
  2. 标识符必须以字母或下划线开头,不能以数字开头。
  3. 标识符区分大小写。
  4. 标识符的长度没有限制,但只有前31个字符有效。
  5. C语言的关键字(如if、for、while等)不能用作标识符。
  6. 标识符不能包含空格或其他特殊字符(如@、#、$等)。
  7. 一般情况下,标识符应具有描述性和易于理解的名称。

四、类的访问限定符和封装

访问限定符

C++中访问限定符有三个,分别是:public(公有的)protected(被保护的)private(私有的)

访问限定符的说明

public修饰的成员在类外可以直接访问

protec和private修饰的成员再类外面不能直接访问(目前认为他两一样,到后面介绍了继承、多态再解释他两的区别)

访问权限的作用域该访问限定符开始到下一个访问限定符结束, 如果没有出现下一个访问限定符,则到}终止

class的默认访问权限是private的,struct为public的(因为struct要兼容C语言)

注意:访问限定符只要编译时有效,当数据映射到内存后,没有任何访问限定符上的区别

OK, 举个栗子看看:

public(在类外可以访问,以属性举例,方法同理):

class Stack
{
public:void Init(int capacity = 3){_a = (int*)malloc(sizeof(int) * capacity);if (_a == nullptr){perror("malloc failed");exit(-1);}_size = 0;_capacity = capacity;}void Push(int x){//...}int* _a;int _size;int _capacity;
};int main()
{Stack s;s.Init();cout << s._size << endl;return 0;
}

这里把class直接换成struct也可以!

private/protectedd当前认为是一样的,在类外不可访问:

C++中struct和class的区别是什么?

C++需要兼容C语言,所以C++中的struct可以当成结构体使用。另外C++中的struct还可以和class一样用来定义类。区别是struct定义类的访问权限是public,class定义的类的访问权限是private。另外在继承和模板参数列表位置也是与区别的(后期介绍了会在拿出来介绍的)!

注意:在C++中如果用struct定义结构体的话,在结构体类在申明结构体变量时,不用在+struct了

struct SLNode
{int* data;SLNode* next;
};

原因是:C++对struct进行了升级变成了类,用它定义的就是一个类型,所以就可以直接用,C语言是struct _name{}才是一个类型!

封装

理论层面:C++实现封装的方式:用类将对象的属性和方法结合到一块,让对象更加完善,通过访问权限来隐藏内部具体的实现细节选择性的把其部分接口提供给外部调用者(用户)。

代码层面:在C++类的内部,把不想让类外部直接访问的成员用private修饰,外部要访问只能使用提供公开的接口!

封装的本质是一种管理,为了让用户使用起来方便!

OK,来举一个栗子。你现在看这篇博客的手机或电脑,它的组成较为复杂,他只给用户提供开机键,输入输出设备即键盘显示器等让用户和计算机能进行交互的接口,但他真正工作的是CPU显卡等硬件!但你用关心这些吗?是不是不用啊!你只需要在人家给你的提供的接口上操作即可,管他的谁工作、如何工作。只要能完成你的操作即可~!

五、类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类外面定义时,需要使用::作用域限定符来指定成员属于哪个类!

class Date
{
public:void Init(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print();private:int _year;int _month;int _day;
};//这里注意要指定Print属于Date这个类
void Date::Print()
{cout << "999" << endl;
}

六、类的实例化

用类类型创建对象的过程,称为类的实例化。

//类
class Date
{
public:void Init(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d;//实例化一个对象d.Init(2023, 11, 25);d.Print();return 0;
}

1、类是描述对象的,是一个模型(模板),它限制了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储他。例如:开学时填写的学生信息表,这个表可以看成一个学生类,他来描述具体的学生(对象)!

2、一个类可以实例化多个对象,实例化出来的对象占用实际的物理空间,存储类成员变量

例如:刚刚上面说的把学生开学的信息表看做一个学生类的话,每登记一个学生就实例化了一个对象,而这个表可以被很多学生填写(实例化多个对象)!每个实例化出来的学生对象才有自己的实际空间(例如宿舍),这些学生有属于自己的年龄、姓名、性别等成员属性!

或者:你可以把盖楼房的图纸理解成一个类,按照这个图纸可以修很多的房子(实例化多个对象),图纸本身不占实际的空间,真正占空间的是按照图纸盖的房子,这些实例化的房子有客厅、卧室等属性!

七、类对象模型

上面我们已经清楚了类的定义以及其实例化对象。一个对象有成员属性也有成员的方法,而我们想知道的是一个对象包含了什么?

OK,关于这个问题我就直接先说结论,再解释了:

一个对象包含了成员属性和成员方法。成员属性是对象自身的属性(成员变量),也就是说成员属性属于对象。而成员方法是这个类都有的行为是属于类(所有类的对象都有成员)。

我用一个我家鸽鸽的例子来说明:我家鸽鸽属于人这个类,他的名字和性别等是他个人独属于的!他的成员方法(行为)有:唱、条、rap、打篮球。但只有我家鸽鸽会唱、条、rap、打篮球吗?你是不是也可以啊,所以类的成员方法属于类!

class People
{
public://方法属于整个类void Sing(){cout << "鸡你太美~..." << endl;}private://属性属于对象本身char _name[20];char _sex[5];int age;
};

如何计算一个类的大小?

可以用sizeof这个操作符来计算类的大小!一个类的大小是该类中的成员变量之和(不包含静态成员变量,虽然静态成员变量属于类但对类的大小无影响),当然要注意内存对齐!如果是没有成员变量的类,编译器会给一个字节来唯一标识这个类

//既有成员变量又有成员方法的类
class A
{
public:void Print(){//...}private:int a;
};//只有成员方法没有成员变量的类
class B
{
public:void Print(){//...}
};//既没有成员变量有没有成员方法的类(空类)
class C
{};int main()
{cout << sizeof(A) << endl;cout << sizeof(B) << endl;cout << sizeof(C) << endl;return 0;
}

目前我们可以认为类的大小和对象的大小是一样的!一个是在图纸上算空间,一个是实地测量!

结构体内存对齐规则(和C语言的一样)

1.结构的第一个成员变量永远放在相较于结构体起始位置偏移量为0处!

2.从第二个开始,后面的每个元素都要对齐到某个对齐数的整数倍处!对齐数:结构体成员自身大小和默认对齐数的较小值!

在VS上默认对齐数是8,而在gcc是没有默认对齐数的(对齐数就是成员的自身大小)!

3.结构体的总大小,必须是最大对齐数的整数倍。最大对齐数:所有成员的对齐数中的最大值!

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍(包含嵌套结构体的对齐数)!

如果这块还有问题,请点击后面的链接,这篇博文中我详细介绍过它的计算和栗子:

内存对齐

八、this指针

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;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Init(2023, 11, 25);d1.Print();Date d2;d2.Init(2023, 11, 26);d2.Print();return 0;
}

Init和Print是类的成员方法,我们并没有指定是哪个对象的,为什么我们在调d1.Init的时候就是给d1对象赋值而不是给d2初始化呢?我们在d2.Print的时候是打印d2的属性的信息,为什么不打印d1会随机值呢????他到底是如何区别的呢?

C++为了解决上述的问题引入了this指针来解决!C++编译器给每一个静态的成员函数都增加了一个隐藏的指针参数,让这个指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有的成员变量的操作,都是通过该指针去访问的。只不过所有的操作对用户是不可见的,也不需要用户手动传,编译器会自动完成!!

this指针的特性

1、this指针的类型:类类型* const ,即此时的const修饰this,只能在形参接受被实参拷贝的时候赋值一次,在成员函数中,不能给this赋值

2、this只能在成员函数(非静态成员函数,静态的成员函数没有this后面会再解释)内部使用,可以显示的写

3、this指针本质成员函数的形参(非静态成员函数),当对象调用成员函数,将对象的地址会传给this,所以对象不存储this指针

4、this指针成员函数(非静态成员函数)第一个隐含的指针参数(形参),一般情况由寄存器ecx自动传递,调用者不需要手动传递

this指针存在哪里?this指针可以为空吗?

这应该是这里很坑的两个问题了,对基础考察很细!OK,我还是先说结论,再用栗子来解释!

this指针是形参,存储在函数栈帧上!this可以为空,但为空时不能去访问成员属性否则就是则空指针异常操作了!

OK,两个栗子分别解释一下:

栗子1:下列程序的编译运行的结果是?A、编译报错  B、运行奔溃  C、正常运行

class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

OK,他是C、正常运行!我们来看一下:

原因是:这里虽然p是nullptr但他是个对象指针,他->Print是调用类的方法,当然没有问题!他调用Print传参的时候的确是nullpttr,this指针接收的是nullptr但他没有访问成员属性啊!所以不会报错!正常运行!

这里可能有点绕,我来举个栗子,这里的p假设是一个叫张三驴的学霸,它的分数是700,他可不可以报清华?当然可以。人家之人你的分数,不管你的人。这里也是一样,人家直看你是不是类的对象,不管你是不是nullptr 。咱们的张三驴同学虽然收到了很多学校的抢人电话并提前发了录取通知书,但他不去上,是不是就和他没有关系了。这里也是一样,我this的确是nullptr但我没用它访问成员变量呀!

栗子2:下列程序的编译运行的结果是?A、编译报错  B、运行奔溃  C、正常运行


class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->PrintA();return 0;
}

OK,这里是B、运行崩溃!

原因是对空指针进行了操作!和上面的不一样的是下面的Print访问了成员员变量_a,这就出问题了,this是空,指向一块不存在的内存,你咋访问!就出问题了!还是上面的例子:我们的张三驴同学不小心收到了清京大学,一激动以为是那两所顶尖高校合作的一个学校。可高兴了,结果把学费一交都查不到学校地址~.....

C语言和C++实现栈的对比

C语言

#include <assert.h>
typedef int DataType;
typedef struct Stack
{DataType* array;int capacity;int size;
}Stack;void StackInit(Stack* ps)
{assert(ps);ps->array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == ps->array){assert(0);return;}ps->capacity = 3;ps->size = 0;
}void StackDestroy(Stack* ps)
{assert(ps);if (ps->array){free(ps->array);ps->array = NULL;ps->capacity = 0;ps->size = 0;}
}void CheckCapacity(Stack* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity * 2;DataType* temp = (DataType*)realloc(ps->array,newcapacity * sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!!");return;}ps->array = temp;ps->capacity = newcapacity;}
}void StackPush(Stack* ps, DataType data)
{assert(ps);CheckCapacity(ps);ps->array[ps->size] = data;ps->size++;
}int StackEmpty(Stack* ps)
{assert(ps);return 0 == ps->size;
}void StackPop(Stack* ps)
{if (StackEmpty(ps))return;ps->size--;
}DataType StackTop(Stack* ps)
{assert(!StackEmpty(ps));return ps->array[ps->size - 1];}int StackSize(Stack* ps)
{assert(ps);return ps->size;
}int main()
{Stack s;StackInit(&s);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);StackPush(&s, 4);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackPop(&s);StackPop(&s);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackDestroy(&s);return 0;
}
可以看到,在用 C 语言实现时, Stack 相关操作函数有以下共性:
每个函数的第一个参数都是 Stack*
函数中必须要对第一个参数检测,因为该参数可能会为 NULL
函数中都是通过 Stack* 参数操作栈的
调用时必须传递 Stack 结构体变量的地址
结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即 数据和操作数据
的方式是分离开的 ,而且实现上相当复杂一点,涉及到大量指针操作,稍不注意可能就会出
错。

C++:

typedef int DataType;
class Stack
{
public:void Init(){_array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = 3;_size = 0;}void Push(DataType data){CheckCapacity();_array[_size] = data;_size++;}void Pop(){if (Empty())return;_size--;}DataType Top() { return _array[_size - 1]; }int Empty() { return 0 == _size; }int Size() { return _size; }void Destroy(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}private:void CheckCapacity(){if (_size == _capacity){int newcapacity = _capacity * 2;DataType* temp = (DataType*)realloc(_array, newcapacity *sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!!");return;}_array = temp;_capacity = newcapacity;}}private:DataType* _array;int _capacity;int _size;
};int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);printf("%d\n", s.Top());printf("%d\n", s.Size());s.Pop();s.Pop();printf("%d\n", s.Top());printf("%d\n", s.Size());s.Destroy();return 0;
}
C++ 中通过类可以将数据 以及 操作数据的方法进行完美结合,通过访问权限可以控制那些方法在 类外可以被调用,即封装 ,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。
而且每个方法不需要传递 Stack* 的参数了,编译器编译之后该参数会自动还原,即 C++ Stack * 参数是编译器维护的, C 语言中需用用户自己维护

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/172241.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基本数据结构二叉树(1)

目录 1.树概念及结构 1.1树的概念 1.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树概念及结构 2.1概念 2.2现实中的二叉树&#xff1a; 2.3 特殊的二叉树&#xff1a; 2.5 二叉树的存储结构 2. 链式存…

【多线程】-- 03 龟兔赛跑案例线程创建方法之三:Callable接口

多线程 2 线程创建 【续】2.2 龟兔赛跑案例 首先需要一个赛道距离&#xff0c;然后会距离终点越来越近判断比赛是否结束打印出胜利者龟兔赛跑开始故事中是乌龟获胜&#xff0c;兔子需要睡觉&#xff0c;所以要模拟兔子睡觉最终&#xff0c;乌龟赢得比赛 package com.duo.de…

C语言数据类型和变量

# C语言数据类型和变量 # 数据类型介绍 C语⾔提供了丰富的数据类型来描述⽣活中的各种数据。使⽤整型类型来描述整数&#xff0c;使⽤字符类型来描述字符&#xff0c;使⽤浮点型类型来描述⼩数。所谓“类型”&#xff0c;就是相似的数据所拥有的共同特征&#xff0c;编译器只有…

[ruby on rails] array、jsonb字段

一、jsonb # 新增 add_column :shi_tis, :setting, :jsonb, default: {}# string转jsonb def changechange_column :users, :setting, :jsonb, using: setting::jsonb, default: {} end# 加索引 add_index :users, :setting, using: :gin # 这样就为setting jsonb字段创建了一…

TypeScript中的枚举是什么?

在TypeScript中&#xff0c;枚举&#xff08;Enum&#xff09;是一种用于定义一组有命名的常量值的数据类型。它们可以提供更具可读性和可维护性的代码。 枚举的作用是为一组相关的值提供一个易于理解和使用的命名空间。它们可以用于代表一系列可能的选项、状态或标志&#xf…

CMake Error:No targets specified and no makefile found

在适用cmake构建项目的时候&#xff0c;突然遇到了这个报错 Make Error at CMakeLists.txt:1 (project): VERSION not allowed unless CMP0048 is set to NEW – Configuring incomplete, errors occurred! make: *** No targets specified and no makefile found. Stop. CMake…

MySQL进阶知识

目录 MySQL的Linux安装 存储引擎 MySQL的体系结构 存储引擎简介 存储引擎特点 InnoDB 逻辑存储结构 MyISAM Memory 对比 存储引擎选择 索引 介绍 索引结构 BTree索引 Hash索引 索引分类 索引语法 SQL性能分析 SQL执行频率 慢查询日志 profile详情 expla…

CRC 循环冗余检测

目录 一、基础知识1.异或运算xor2.模2算术&#xff08;1&#xff09;模2加法和减法&#xff08;2&#xff09;模2乘法&#xff08;3&#xff09;模2除法 二、CRC循环冗余检测1.背景2.原理3.求R 一、基础知识 1.异或运算xor 异或&#xff0c;顾名思义&#xff0c;只有当两个数…

算法基础一

两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 解题思路&#xff1a;这道题最优的做法时间复杂度是O(n)&#xff0c;顺序扫描数组&#xff0c;对每一个元素在…

Aibote4j java封装版本的

Aibote4j 交流Q群&#xff1a;496086899 开源地址&#xff1a;https://github.com/1341191074/aibote4j 更新yolo和ocr相关新增的能力&#xff0c;比较强劲了 下面是使用的案例 public class WebBotTest extends WebBot {public static void main(String[] args) {WebBotSer…

最新AI创作系统ChatGPT网站运营源码、支持GPT-4-Turbo模型,图片对话识图理解,支持DALL-E3文生图

一、AI创作系统 SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01;本系统使用NestjsVueTypescript框架技术&#xff0c;持续集成AI能力到本系统。支持OpenAI DALL-E3文生图&#xff0c;…

事件委派+自定义属性+编程式导航实现路由跳转及传参

当我们页面中有许多a标签需要实现点击跳转到同一个页面并携带不同的参数时&#xff0c;我们就可以使用事件委派自定义属性编程式导航 的方式&#xff0c;用最小的内存实现路由跳转的最大效率。 为什么我们不用router-link 进行跳转&#xff1f; 要知道&#xff0c;我们页面中…

【单调栈】子数组的最小值之和

import java.util.Deque; import java.util.LinkedList;/** 参考链接&#xff1a;https://leetcode.cn/problems/sum-of-subarray-minimums/solutions/1930857/gong-xian-fa-dan-diao-zhan-san-chong-shi-gxa5/* https://leetcode.cn/problems/sum-of-subarray-minim…

Docker 的基本概念和优势,以及在应用程序开发中的实际应用。

Docker 是一种容器化技术&#xff0c;它将一个应用程序及其所有依赖项打包在一起&#xff0c;形成一个独立的、可移植的容器。这个容器可以在任何支持 Docker 的操作系统上运行&#xff0c;而且具有很好的可移植性和可扩展性。以下是 Docker 的基本概念和优势&#xff1a; 镜像…

论文公式和代码对应

NGCF 论文地址 NGCF模型全部代码 import torch import torch.nn as nn import torch.nn.functional as F class NGCF(nn.Module):def __init__(self, n_user, n_item, norm_adj, args):super(NGCF, self).__init__()self.n_user n_userself.n_item n_itemself.device args…

数据结构与算法(Java)-树形DP题单

树形DP&#xff08;灵神笔记&#xff09; 543 二叉树的直径 543. 二叉树的直径 - 力扣&#xff08;LeetCode&#xff09; 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根…

使用 Java 客户端通过 HTTPS 连接到 Easysearch

Easysearch 一直致力于提高易用性&#xff0c;这也是我们的核心宗旨&#xff0c;然而之前一直没有官方的 Java 客户端&#xff0c;也对用户使用造成了一些困扰&#xff0c;现在&#xff0c;我们正式发布了第一个 Java 客户端 Easysearch-client:1.0.1。 这一里程碑式的更新为开…

成为AI产品经理——TPR、FPR、ROC、AUC

目录 一、PR图、BEP 1.PR图 2.BEP 二、灵敏度、特异度 1.灵敏度 2.特异度 三、真正率、假正率 1.真正率 2.假正率 三、ROC、AUC 1.ROC 2.AUC 四、KS值 一、PR图、BEP 1.PR图 二分类问题模型通常输出的是一个概率值&#xff0c;我们需要设定一个阈值&#xff…

Android aidl的简单使用

一.服务端 1.创建aidl文件&#xff0c;然后记得build下生成java文件 package com.example.aidlservice31;// Declare any non-default types here with import statementsinterface IMyAidlServer {// 接收一个字符串参数void setData(String value);// 返回一个字符串String …

数据结构与算法之贪心: LeetCode 122. 买卖股票的最佳时机II (Typescript版)

买卖股票的最佳时机II 给你一个整数数组 prices &#xff0c;其中 prices[i] 表示某支股票第 i 天的价格。 在每一天&#xff0c;你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买&#xff0c;然后在 同一天 出售。 返回 你能获得的 …