C++之对象模型和this 指针,友元,和运算符重载

news2024/10/7 10:13:59

1,对象模型和this 指针

1.1成员变量和成员函数分开存储

在C++中,类内的成员变量和成员函数分开存储

只有非静态成员变量才属于类的对象上

示例:

#include<iostream>
using namespace std;

//成员变量 和 成员函数 分开存储
class Person
{
	int m_A;//非静态成员变量 属于类对象上

	static int m_B;//静态成员变量 不属于类对象上

	void func() {}//非静态成员函数 不属于类对象上

	static void func2() {}//静态成员函数 不属于类对象上
};

int Person::m_B = 0;

void test01()
{
	Person p;
	//空对象占用内存空间为:1
	//编译器会给每个空对象也分配一个字节的空间,是为了区分空对象占内存的位置
	//每个空对象都有独一无二的内存地址
	cout << "sizeof p =" << sizeof(p) << endl;
}
void test02()
{
	Person p;
	cout << "size of p=" << sizeof(p) << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

1.2 this指针概念

 C++中成员变量和成员函数是分开存储的
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

那么问题是:这一块代码是如何区分那个对象调用自己的呢?
this指针指向被调用的成员函数所属的对象c++通过提供特殊的对象指针,this指针,解决上述问题。

this指针指向被调用的成员函数所属的对象
this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可

this指针的用途:
当形参和成员变量同名时,可用this指针来区分
在类的非静态成员函数中返回对象本身,可使用return*this

#include<iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		//1,当形参和成员变量同名时,用this指针来区分
		this->age = age;
	}

	Person& PersonAddPerson(Person p)
	{
		this->age += p.age;
		//返回对象本身
		return *this;
	}
	int age;
};

void test01()
{
	Person p1(10);
	cout << "p1.age = " << p1.age << endl;

	Person p2(10);
	p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
	cout << "p2.age = "<<p2.age << endl;

	
}

int main()
{
	test01();

	system("pause");

	return 0;
}

1.3 空指针访问成员函数

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针

如果用到this指针,需要加以判断保证代码的健壮性

错误示范:

#include<iostream>
using namespace std;
#include<string>

//空指针访问成员变量
class Person
{
public:
	void ShowClassName()
	{
		cout << "我是Person类!" << endl;
	}
	void ShowPersonAge()
	{
		//报错原因因为传入的指针时为NULL
		cout << "age=" << m_Age << endl;
		if (this == NULL)
		{
			return;
		}
		cout << "this is Person class" << endl;
	}
	int m_Age;
};

void test01()
{
	Person* p = NULL;

	p->ShowClassName();

	p->ShowPersonAge();
}

int main()
{
	test01();

	system("pause");

	return 0;
}

 正确示范:

#include<iostream>
using namespace std;
#include<string>

//空指针访问成员变量
class Person
{
public:
	void ShowClassName()
	{
		cout << "我是Person类!" << endl;
	}
	void ShowPersonAge()
	{
		//报错原因因为传入的指针时为NULL
		
		if (this == NULL)
		{
			return;
		}
		cout << "age=" << this->m_Age << endl;
	}
	int m_Age;
};

void test01()
{
	Person* p =NULL;

	p->ShowClassName();

	p->ShowPersonAge();
}

int main()
{
	test01();

	system("pause");

	return 0;
}

1.4 const修饰成员指针

常函数:

  成员函数后加const后我们称这个函数为常函数

  常函数内不可以修改成员属性

  成员属性声明时加关键字nutable后,在常函数中依然可以修改

常对象:

声明对象前加const称该对象为常对象

常对象只能调用常函数 

示例:

#include<iostream>
using namespace std;
#include<string>
class Person
{
public:
	//this指针的本质 是指针常量  指针的指向是不可以修改的
	//const Person * const this;
	//在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
	void showPerson() const
	{
		//this->m_A = 100;
		//this = NULL;//this指针不可以修改指针的指向的值
	}

	void func()
	{

	}
	int m_A;
	mutable int m_B;//特殊变量 即使变量在常函数中,也可以修改这个值,加关键字mutable
};


void test01()
{
	Person p;
	p.showPerson();
}

void test02()
{
	const Person p;
	//p.m_A = 100;
	p.m_B = 100;//m_B是特殊值,在常对象下也可以修改

	p.showPerson();
	//p.func();//常对象 不可以调用普通成员函数,因为普通成员函数可以修改属性
}

int main()
{
	test01();

	test02();

	system("pause");

	return 0;
}

2,友元

生活中你的家有客厅(Public),有你的卧室(Private)
客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去
但是呢,你也可以允许你的好闺蜜好基友进去。 


在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术


友元的目的就是让一个函数或者类 访问另一个类中私有成员


友元的关键字为 friend


友元的三种实现
2.1 全局函数做友元

示例:

#include<iostream>
using namespace std;
#include<string>

//建筑物类
class Building
{
	//告诉编译器 goodGay全局变量 是 Building 类的好朋友,可以访问类中的私有内容
	friend void goodGay(Building* building);

public:
	Building()
	{
		m_Sittingroom = "客厅";
		m_Bedroom="卧室";
	}

public:
	string m_Sittingroom;//客厅
private:
	string m_Bedroom;//卧室
};

//全局函数
void goodGay(Building* building)
{
	cout << "好基友全局变量 正在访问:" << building->m_Sittingroom << endl;

	cout << "好基友全局变量 正在访问:" << building->m_Bedroom  << endl;

}

void test01()
{
	Building building;
	goodGay(&building);
}

int main()
{
	test01();

	system("pause");

	return 0;
}


2.2 类做友元

#include<iostream>
using namespace std;
#include<string>

class Building
{
	friend class GoodGay;

public:
	public:
		Building();

	string m_SettingRoom;

private:
	string m_Bedroom;

};

class GoodGay
{
public:
	GoodGay();

public:

	void visit();//参观函访问building中的属性

	Building* building;
};

//类外写成员函数
Building::Building()
{
	m_SettingRoom = "客厅";
	m_Bedroom = "卧室";
}

GoodGay::GoodGay()
{
	//创建建筑物对象
	building = new Building;
}

void GoodGay::visit()

{
	cout << "好基友正在访问:" << building->m_SettingRoom << endl;

	cout << "好基友正在访问:" << building->m_Bedroom<< endl;
}
void test01()
{
	GoodGay gg;
	gg.visit();
}

int main()
{
	test01();

	system("pause");

	return 0;
}


2.3 成员函数做友元

#include<iostream>
using namespace std;
#include<string>

class Building;

class GoodGay
{
public:
	GoodGay();

	void visit();//让visit函数访问Building中私有成员
	void visit2();//让visit2函数不可以访问Building中私有成员

	Building* building;
};
class Building
{
	//告诉编译器 GoodGay类下的visit成员函数作为本类的好朋友,可以访问私有成员
	friend void GoodGay::visit2();
public:
	Building();
public:
	string m_SittingRoom;//客厅
private:
	string m_Bedroom;//卧室
};

//类外实现成员函数
Building::Building()
{
	m_SittingRoom = "客厅";
	m_Bedroom = "卧室";
}

GoodGay::GoodGay()
{
	building = new Building;
}

void GoodGay::visit()
{
	cout << "visit 函数正在访问:" << building->m_SittingRoom << endl;
	//cout << "visit2 函数正在访问:" << building->m_Bedroom << endl;
}
void GoodGay::visit2()
{
	cout << "visit2 函数正在访问:" << building->m_SittingRoom << endl;
	cout << "visit2 函数正在访问:" << building->m_Bedroom << endl;
}
void test01()
{
	GoodGay gg;
	gg.visit();
	gg.visit2();
}

int main()
{
	test01();

	system("pause");

	return 0;
}

3,运算符重载

概念:对已有的运算符重新定义,赋予其另一种功能,以适应不同数据类型

3.1 加号运算符重载

作用:实现两个自定义数据类型

方式一: 成员函数重载

#include<iostream>
using namespace std;
#include<string>

class Person
{
public:
	//1,成员函数重载+号
	Person operator+(Person& p)
	{
		Person temp;
		temp.m_A = this->m_A + p.m_A;
		temp.m_B = this->m_B + p.m_B;
		return temp;
	}

	int m_A;
	int m_B;
};

void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;

	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;

	//成员函数重载本质调用
	Person p3 = p1.operator+(p2);
	cout << "p3.m_A = " << p3.m_A << endl;
	cout << "p3.m_B = " << p3.m_B << endl;
	cout << endl;

}

int main()
{
	test01();

	system("pause");

	return 0;
}

 方式二:全局函数重载+号

#include<iostream>
using namespace std;
#include<string>

class Person
{
public:
	int m_A;
	int m_B;
};

//2,全局函数重载+号
Person operator+(Person& p1, Person& p2)
{
	Person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}


void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;

	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;

	//全局函数重载本质调用
	Person p3 = operator+(p1, p2);
	//简化为Person p3 = p1 + p2;
	cout << "p3.m_A = " << p3.m_A << endl;
	cout << "p3.m_B = " << p3.m_B << endl;
	cout << endl;

}

int main()
{
	test01();

	system("pause");

	return 0;
}

 

方式三:运算符重载 也能发生函数重载

#include<iostream>
using namespace std;
#include<string>

class Person
{
public:
	int m_A;
	int m_B;
};

Person operator+(Person& p1, int num)
{
	Person temp;
	temp.m_A = p1.m_A + num;
	temp.m_B = p1.m_B + num;
	return temp;
}

//函数重载的版本
void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;

	Person p4 = p1+100;//Person + int

	cout << "p4.m_A = " << p4.m_A << endl;
	cout << "p4.m_B = " << p4.m_B << endl;
	cout << endl;

}

int main()
{
	test01();

	system("pause");

	return 0;
}

 

总结1:对于内置的数据类型的表达式的运算符是不可能改变的

总结2:不要滥用运算符重载 

3.2 左移运算符重载

作用:可以输出自定义数据类型

#include<iostream>
using namespace std;
#include<string>

class Person
{
	friend ostream& operator<<(ostream &cout, Person &p);
public:
	Person(int a, int b)
	{
		this->m_A=a;
		this->m_B=b;
	}

	//利用成员函数重载 左移运算符 p.operator<<(cout)  简化版本 p<<cout
	// 不会利用成员函数重载<<运算符,因为无法实现cout在左侧
	//void operator<<(Person& p)
	//{
	//
	//}

private:
	int m_A;
	int m_B;
};

//只能利用全局函数重载左移运算符
//ostream对象只能有一个
ostream & operator<<(ostream & cout, Person & p)//本质 operator<<(cout,p)  简化版本 cout<<p
{
	cout << "m_A= " << p.m_A << "m_B" << p.m_B;
	return cout;
}

void test()
{
	Person p(10, 20);
	//p.m_A = 10;
	//p.m_B = 10;
	cout << p <<" "<< "hello world" << " " << endl;//链式编程
}
int main()
{
	test();

	system("pause");

	return 0;
}

总结:重载左移运算符配合友元可以实现输出自定义数据类型 

3.3  递增运算符重载

#include<iostream>
using namespace std;
#include<string>

//自定义整型
class MyInterger
{
	friend ostream& operator<<(ostream& cout, MyInterger myint);
public:
	MyInterger()
	{
		m_Num = 0;
	}

	//重载前置++,返回引用为了一直对一个数据进行递增操作
	MyInterger& operator++()
	{
		//先进行++运算
		m_Num++;
		//再将自身返回
		return *this;
	}
	//重载后置++
	MyInterger& operator++(int)//int 代表占位参数,可以用于区分前置和后置递增
	{
		//先记录当时结果
		MyInterger temp = *this;
		//后递增
		m_Num++;
		//最后将记录结果返回
		return temp;
	}
private:
	int m_Num;
};

//重载左移运算符
ostream& operator<<(ostream& cout, MyInterger myint)
{
	cout << myint.m_Num;
	return cout;
}
void test01()
{
	MyInterger myint;

	cout << ++myint << endl;
	cout << endl;
}

void test02()
{
	MyInterger myint;

	cout <<myint++ << endl;
	cout << myint << endl;
}

int main()
{
	test01();

	test02();

	system("pause");

	return 0;
}

 

3.4  赋值运算符重载

C++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
4.赋值运算符 operator=,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题 

示例:

#include<iostream>
using namespace std;
#include<string>

//自定义整型
class Person
{
	friend void test01();
public:
	Person(int age)
	{
		m_Age = new int(age);
	}

	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}
	int *m_Age;
};

void test01()
{
	Person p1(18);

	Person p2(20);

	p2 = p1;//赋值操作

	cout << "p1的年龄为:" << *p1.m_Age << endl;

	cout << "p2的年龄为:" << *p2.m_Age << endl;
}

int main()
{
	test01();


	system("pause");

	return 0;
}

以上代码程序会崩溃,解释如下图所示

#include<iostream>
using namespace std;
#include<string>

//自定义整型
class Person
{
	friend void test01();
public:
	Person(int age)
	{
		m_Age = new int(age);
	}

	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}
	//重载
	Person& operator= (Person& p)
	{
		//编译器提供浅拷贝
		//m_Age = p.m_Age;

		//应该先判断是否有属性在堆区,如果有先释放干净,然后在深拷贝
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		//深拷贝
		m_Age = new int(*p.m_Age);

		//返回本身对象
		return *this;
	}

	int *m_Age;
};


void test01()
{
	Person p1(18);

	Person p2(20);

	p2 = p1;//赋值操作

	cout << "p1的年龄为:" << *p1.m_Age << endl;

	cout << "p2的年龄为:" << *p2.m_Age << endl;
}

int main()
{
	test01();


	system("pause");

	return 0;
}

 

3.5 关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

#include<iostream>
using namespace std;
#include<string>

//自定义整型
class Person
{
	friend void test01();
public:
	Person(string name,int age)
	{
		m_Name = name;
		m_Age =age;
	}

	//重载==号
	bool operator==(Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		return false;
	}
	bool operator != (Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return false;
		}
		return true;
	}

	int m_Age;
	string m_Name;
};


void test01()
{
	Person p1("Tom",18);

	Person p2("Tom",20);

	if (p1 == p2)
	{
		cout << "p1和p2是相等的!" << endl;
	}
	else
	{
		cout << "p1和p2是不相等的!" << endl;
	}
	if (p1 != p2)
	{
		cout << "p1和p2不是相等的!" << endl;
	}
	else
	{
		cout << "p1和p2是相等的!" << endl;
	}
}

int main()
{
	test01();


	system("pause");

	return 0;
}

 

3.6 函数调用运算符重载

函数调用运算符()也可以重载

 由于重载后使用的方式非常像函数的调用,因此称为仿函数

仿函数没有固定写法,非常灵活

#include<iostream>
using namespace std;
#include<string>

//自定义整型
class MyPrint
{
public:
	//重载函数的调用运算符
	void operator()(string text)
	{
		cout << text << endl;
	}

	void myFunc02(string text)
	{
		cout << text << endl;
	}
};

//仿函数非常灵活,没有固定的写法
//加法类
class MyAdd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};

void test01()
{
	//重载的()操作符也称为仿函数
	MyPrint myFunc;

	myFunc("hello world");//由于使用起来非常类似于函数调用,因此称为仿函数

	string myFunc02("Hello World");

	
}

void test02()
{
	MyAdd myadd;
	int ret = myadd(100, 100);
	cout << "ret = " << ret << endl;

	//匿名对象
	cout << MyAdd()(100, 100) << endl;
}

int main()
{
	test01();
	test02();

	system("pause");

	return 0;
}

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

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

相关文章

Vue3全家桶 - Vue3 - 【6】组件(注册组件 + 组件通信 + 透传属性和事件 + 插槽 + 单文件CSS + 依赖注入)

组件 一、 注册组件 1.1 ❌ 全局注册 目标文件&#xff1a;main.js&#xff1b;语法&#xff1a;import { createApp } from vue import App from ./App.vue const app createApp(App)// 全局注册 app.component(组件名字, 需要注册组件)app.mount(#app)缺陷&#xff1a; 全…

怎样在CSDN赚点零花钱

请教一下各位大佬&#xff0c;看到你们在CSDN很多都几万粉丝以上&#xff0c;能不能分享一下有什么涨粉的经验&#xff0c;还有怎样转化为额外收益……感谢各位提供宝贵的经验&#xff0c;谢谢……

多目灰度cam手势追踪系统——MegaTrack

一、前言 本文是对Facebook Oculus发布的一篇VR方向&#xff08;手势追踪&#xff09;论文的解读。Oculus是一家做VR的公司&#xff0c;2014年被FaceBook收购了&#xff0c;本次参考的论文就是FaceBook Oculus团队的最新论文。论文2020年7月发表于SIGGRAPH。 因为最终是要给大…

Go语言简介

一.Go语言简介 1.1 优点 自带gc静态编译&#xff0c;编译好后&#xff0c;扔服务器直接运行简单思想&#xff0c;没有继承&#xff0c;多态和类等丰富的库和详细开发文档语法层支持并发&#xff0c;和拥有同步并发的channel类型&#xff0c;使并发开发变得非常方便简洁语法&am…

手机和电脑同步的好用记事本软件有哪些

我常常需要随手记录各种信息&#xff0c;以便随时查阅和使用。比如&#xff0c;在下班路上&#xff0c;我会用手机记录明天要处理的工作事项、购物清单&#xff0c;或是某个突然迸发的创意想法&#xff1b;而在办公室&#xff0c;我则需要在电脑上整理会议纪要、项目计划&#…

[AutoSar]BSW_Com012 CAN TP 模块介绍

目录 关键词平台说明一、知识储备二、缩写对照表三、CAN TP 所在架构位置四、CAN TP 的主要作用五、CAN TP 在 autosar 架构中的基本概念5.1、CAN TP 的处理模式5.2 数据一致性5.3 静态配置 六、功能规范6.1 Services provided to upper layer6.1.1 Initialization and shutdow…

基于cnn的卷机神经网络的项目毕业课题实践应用(毕业选题-深度学习-卷及神经网络)

这些项目可以作为毕业课题选择&#xff0c;共计超过20个&#xff1a; 往期热门项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别…

Mybatis操作sql报错ibatis.binding.BindingException: Parameter ‘empId‘ not found.

你们好&#xff0c;我是金金金。 场景 在使用Mybatis操作sql语句过程当中&#xff0c;更新操作&#xff0c;报错信息如下&#xff1a;Caused by: org.apache.ibatis.binding.BindingException: Parameter ‘empId’ not found. Available parameters are [arg1, arg0, param1, …

PyTorch搭建AlexNet训练集

本次项目是使用AlexNet实现5种花类的识别。 训练集搭建与LeNet大致代码差不多&#xff0c;但是也有许多新的内容和知识点。 1.导包&#xff0c;不必多说。 import torch import torch.nn as nn from torchvision import transforms, datasets, utils import matplotlib as p…

电子价签前景璀璨,汉朔科技革新零售行业的数字化新篇章

新型商超模式数字化“秘密武器”——电子价签 传统纸质价签&#xff0c;只要商品价格、日期等信息发生变化&#xff0c;就必须重新打印进行手动替换。电子价签的应用使传统的人工申请、调价、打印、营业员去货架前端更换等变价流程均可省略&#xff0c;所有门店的价格由后台统…

Linux命令深入学习——列出帮助手册,开机关机

linux中有多种方法查看一个不熟悉命令的详细信息&#xff0c;如 ls --help&#xff0c;help ls&#xff0c;man ls&#xff0c;info ls 在linux系统中可以使用命令进行开关机以及相关基础操作 同时在进行写入操作时&#xff0c;可以使用快捷键进行操作

图论(二)之最短路问题

最短路 Dijkstra求最短路 文章目录 最短路Dijkstra求最短路栗题思想题目代码代码如下bellman-ford算法分析只能用bellman-ford来解决的题型题目完整代码 spfa求最短路spfa 算法思路明确一下松弛的概念。spfa算法文字说明&#xff1a;spfa 图解&#xff1a; 题目完整代码总结ti…

【LeetCode每日一题】2129. 将标题首字母大写

文章目录 [2129. 将标题首字母大写](https://leetcode.cn/problems/capitalize-the-title/)思路&#xff1a;代码&#xff1a; 2129. 将标题首字母大写 思路&#xff1a; 1.先根据空格&#xff0c;将每个单词切割&#xff0c;依次遍历 2.用StringBuilder来对结构进行拼接 3.…

element plust的表格 el-table数据不按列展示

ElementPlus的表格demo代码放到原生的html <template><el-table :data"tableData" style"width: 100%"><el-table-column prop"date" label"Date" width"180" /><el-table-column prop"name"…

使用Python查询和下载Sentinel卫星数据

欢迎学习本教程,了解如何使用 Python 访问和下载 Sentinel 卫星数据。在深入探讨技术方面之前,让我们先了解一下哨兵卫星是什么以及它们为何如此重要。 哨兵家族。资料来源:欧空局。 Sentinel 卫星是欧洲航天局 (ESA) 开发的一组地球观测任务,是哥白尼计划的一部分,该计划…

Spark性能优化指南——高级篇

调优概述 有的时候&#xff0c;我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜&#xff0c;此时Spark作业的性能会比期望差很多。数据倾斜调优&#xff0c;就是使用各种技术方案解决不同类型的数据倾斜问题&#xff0c;以保证Spark作业的性能。 数据倾斜发生时的现…

一文了解Cornerstone3D中窗宽窗位的3种设置场景及原理

&#x1f506; 引言 在使用Cornerstone3D渲染影像时&#xff0c;有一个常用功能“设置窗宽窗位&#xff08;windowWidth&windowLevel&#xff09;”&#xff0c;通过精确调整窗宽窗位&#xff0c;医生能够更清晰地区分各种组织&#xff0c;如区别软组织、骨骼、脑组织等。…

SSM整合项目(校验)

文章目录 1.前端校验1.需求分析2.HomeView.vue的数据池中添加校验规则3.HomeView.vue 绑定校验规则![image-20240311213428771](https://img-blog.csdnimg.cn/img_convert/7770bfa16814a0efd4eb818c9869a5bd.png)4.验证是否生效5.如果验证不通过&#xff0c;阻止用户提交表单1.…

机器学习之分类回归模型(决策数、随机森林)

回归分析 回归分析属于监督学习方法的一种&#xff0c;主要用于预测连续型目标变量&#xff0c;可以预测、计算趋势以及确定变量之间的关系等。 Regession Evaluation Metrics 以下是一些最流行的回归评估指标: 平均绝对误差(MAE):目标变量的预测值与实际值之间的平均绝对差…

webpack5零基础入门-4使用webpack处理less文件

1.安装less npm install less -D 2.创建less文件 .box{width: 100px;height: 100px;background: red; } 3.引入less文件并打包 执行npx webpack 报错无法识别less文件 4.安装less-loader并配置 npm install less-loader9 -D 这里指定一下版本不然会因为node版本过低报错 …