[C++入门系列]——类和对象下篇

news2024/11/18 3:27:31

作者主页

📚lovewold少个r博客主页

   ⚠️本文重点:C++类和对象下篇知识点讲解

👉【C-C++入门系列专栏】博客文章专栏传送门

😄每日一言:宁静是一片强大而治愈的神奇海洋!

目录

前言

再谈构造函数

初始化列表 

explicit关键字

static成员

静态成员函数

静态成员特性总结

友元

友元函数

友元类

内部类

再度理解类和对象

总结


前言

        前段时间主要在博客中讲述了C++类和对象中篇的一些知识点,我们发现C++类特性功能有多强大,同时也相应很复杂。在前面的文章中主要涉及到C++默认的成员函数,包括不限于构造函数,析构函数,拷贝构造函数,赋值运算符重载以及const成员函数等内容,踏上了类和对象的编程之旅。详细请看类和对象中篇文章。

        本章会主要从类和对象的更多特性入手,再次剖析构造函数,通过这篇文章的知识点和前面形成连贯理解,对类和对象有更多的理解。同时,本篇文章还会谈及Static成员,友元,内部类,等关键知识点点讲解,深刻理解C++类和对象中的封装意义。学习C++的过程中,难点一是概念情况较为复杂,需要结合代码去深入理解,同时有很多知识点需要去记忆。C++特性的数量之多就意味着很难去全部使用,大多数人需要掌握的是常用特性,同时对与很多特性其实目前是无法在自己的程序中去理解,而是需要在特定情况下去使用。因此目前我会尽量结合一些特定的代码去理解,当然这种可能看似没有意义的代码不一定真没有意义,而是并非特定的使用场景。


再谈构造函数

        在前面的文章中我们提到,构造机构其实就是一种特殊的成员函数,用于在类进行定义的时候直接初始化。我们不去单独构造它,编译器会默认给类自定义类型的成员进行初始化。

        而今天我们提到构造函数,其本质要实现的目的还是一样的,即在创建对象的时候,编译器调用其构造函数,给对象的每一个成员变量一个合适的初始值。

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

        上述的构造函数可以完成对创建对象赋值,但当这种属于赋予初始值,不能完成称之为初始化。为何这样子说,初始化的意义在于对变量进行赋予有价值的值,避免在后期调用出现随机值等情况影响程序的正常。构造函数体内部可以多次赋值,这本质还不算是真正意义上的初始化。

初始化只初始化一次,即在对象定义的时候就得初始化。那么我们来看下面的一段代码。

const int j;       ❌
const int j = 0;   ✅

对于一个常量需要初始化,有且只有一次机会,且必须初始化。那么针对于这真情况,我们怎么做才能对常量初始化呢。

class Date
{
public:
	Date(int year, int month, int day,const int N)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;

	const int _N = 1;//❌
};
 

        这好比在图纸上搭建房子,要知道类里面都是声明呀,声明可以是初始化么?答案肯定是不可以的。初始化一个变量或者一个常变量,是要先拿到它的内存空间的,而_N显然只是声明出来而未定义!

        那么在构造函数内部给值么?

        编译器不仅diss你没有完成初始化设定项,还提醒你表达式必须是可以修改的左值这意味什么! _N在构造函数内部就已经定义了,而现在又改不了它的值了。

       祖师爷通过类和对象的思想进行封装是好事儿,构造函数也很棒,但牵一发而动全身,作为成员变量又不能在外部去定义,在内部构造函数内部构造函数又拿它没办法。因此,就需要来一个新特性来解决这个问题,就和说慌一样,说一个慌就需要用很多慌去圆。

初始化列表 

        初始化列表:以一个冒号开始,接着睡一个一逗号分隔的数据成员列表,每个成员变量的后面跟着一个放在括号中的初始值或者表达值。

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year) //冒号开始
		,_month(month) //逗号分隔
		,_day(day) //()内部为初始化值
		,_N(1)
	{};
private:
	int _year;
	int _month;
	int _day;

	const int _N;//
};

        初始化列表是这些成员变量定义的地方,这里就相当于在定义的时候就初始化了。终于解决了常变量这个麻烦事儿,当然对于麻烦的事情不仅可以一起处理,也可以分开去处理。

 ⚠️注意:

  • 每一个成员变量在初始化列表中只能出现一次(初始化只初始化一次)

  • 类中包含以下成员的时候必须放在初始化列表进行初始化
    • 引用成员变量        int& _ret;                                                           
    • const成员变量       const int _N;                                                     
    • 自定义成员变量(且该类没有构造函数的时候)      A   _aa;           
  • 尽量使用初始化列表进行初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化

        观察下述代码,Date创建一个对象其本身并没有使用Time _t的成员变量,但是对于自定义类型的成员变了,一定会先使用初始化列表进行初始化。

  • 成员变量在类中的声明次序就是其在初始化列表的初始化顺序,与初始化列表中的前后次序无关

        在类中声明的顺序是先_a2,后_a1,因此在进行初始化时候,先对_a进行初始化,此时_a1未初始化,为随机值,_a2就初始化了为这个随机值。_a1后初始化,接受了参数1,因此初始化了为1。

        当然对于初始化列表的顺序最好要和声明顺序一样,不然出现情况了不能老是弯弯绕绕的分析吧!

explicit关键字

观察下面的代码:

class Date {
public:
	Date(int year)
		: _year(year)
	{
		;
	}
	void Printf()
	{
		cout << _year << endl;
	}

private:
	int _year;
};

int main(void)
{
	Date d1(2022);
	cout << "d1-> ";
	d1.Printf();
	Date d2 = 2022;    // 隐式类型转换
	cout << "d2-> ";
	d2.Printf();

	return 0;
}

        d1没什么好说的,可是d2就有点奇怪了,用一个整形值给d2赋值竟然可以赋值成功。其实这里就发生了隐式类型转换。实际上编译器会用2022这个值构造一个无名对象,最后将无名赋值给d1。这种隐式类型转换是存在的,且在单参数和多参数其第一个参数无缺省值(后两位可以不传参),而其他位均有缺省值得情况下就会发生这些默认的隐式类型转换。这样就会导致代码的可读性变差。因此 explicit 能修饰函数,限制其类型转换作用的发生。

static成员

        static的类成员称之为类的静态成员,用static修饰的成员变量称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员函数变量一定要在类外进行初始化。

        概念不好理解这里我们先来试着写一段代码,来体会一下何为静态成员和静态成员函数。

        现在,我们需要计算我们到底创建了多少个对象。这个很简单,即在所有构造函数内部实现对一个变量的加减即可,如果要计算有多少个对象正被使用也只需要在析构函数对一个变量减值即可

       思路简单,问题来了,变量设置在哪里呢?

       我们设置为全局变量

int N = 0;  // 全局变量计数器
class A {
public:
	A(int a = 0)
		: _a(a) 
	{
		N++;
	}
	A(const A& aa)
		: _a(aa._a) 
	{
		N++;
	}
private:
	int _a;
};
void f(A a)
{
	;
}
int main(void)
{
	A a1;
	A a2 = 1;
	f(a1);
	cout << N << endl;
	return 0;
}

        这一段代码一定可以实现记数功能的,没错!笃定切肯定!但是类和对象核心就是封装,就设置一个变量N,随便外部都可以通过修改全局变量就能改变变量N,怎么能保证功能安全呢。

        我们设置为成员变量,然后问题又来了。

class A {
public:
	A(int a = 0)
		: _a(a) {
		_N++;
	}
	A(const A& aa)
		: _a(aa._a) {
		_N++;
	}

private:
	int _a;
	int _N = 0;  
};

        对于上面的成员变量,每一次创建对象是使用的同一个_N吗?很显然不是,且每一个对象都是使用的this->_N,这就说明没一个对象都有一个_N,这种方案直接否定。还不如上一种全局变量呢,至少还能实现。 因此方案三出来了,static成员函数。

静态成员为所有类共享,不属于某个具体的类,存放在静态区。

class A {
public:
	A(int a = 0)
		: _a(a) {
		_N++;
	}
	A(const A& aa)
		: _a(aa._a) {
		_N++;
	}

//private:
	int _a;
	static int _N;  
};
int A::_N = 0;

        当然解决一个问题又来一个,静态成员首先也是一个成员,受public、protected、private访问限定符的限制。

        因此,对于一个静态成员的访问我们需要怎么样去访问呢?如果它是类的公有成员还好说,直接突破类域即可(即非private)。


int main(void)
{
	A a1;
	A a2 = 1;
	f(a1);
 
	cout << A::_sCount  << endl;  //突破类域进行访问
 
	//这里a1.并非在a1里面,静态成员为所有对象共享,这里只是帮助他突破类域的一种手段 
	cout << a1._sCount << endl;
	cout << a2._sCount << endl;
 
	return 0;

        如果不是公有成员呢,我们是否可以达到这种的目的呢。肯定也是可以的,通过在类内部设置一个Get_N()公有函数拿到这个值就好了。这个时候外部调用对象函数就能得到它了。

静态成员函数

类外调用该函数可以访问到,而静态成员函数就可以不使用对象就可以访问到它。

static int GetCount() 
​​​​​​​{
    return _sCount;
}

静态成员特性总结

  1. 静态成员为所有类共享,不属于某一个具体的对象,只存放与静态区。
  2. 静态成员变量必须在类外定义,定义时候不添加static关键字,类中只是声明
  3. 类静态成员即可用类名::静态成员或者对象.静态成员来访问。
  4. 静态成员函数没有隐藏的this指针不能访问任何非限定静态成员。
  5. 静态成员也是类的成员,受public、protected、private访问限定符的限制。

友元

        何为友元,即作为一个类外部的函数或者类,能访问其friend声明所在类的一种方式。

        我们之前学了操作符重载,对与一个日期类,我们是否也可以通过重载operator<<operator>>实现对日期类的流提取和流输入呢?

        我们先看流输入和流输出的库函数。

        根据函数的原理和返回类型,我们直接开始我们的输入输出流重载。不懂原理目前也没事,可以知道的是coutcin返回值类型是ostreamsitream

class Date
{
public:
	Date(int year = 1970, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{};
	ostream& operator<<(ostream& _cout)
	{
		_cout << _year << "-" << _month << "-" << _day << endl;
		return _cout;
	}

private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2023, 4, 22);
	cout << d1;//无法识别
	return 0;
}

        这里依旧识别不了,双操作数的运算符重载时,规定第一个参数是左操作数,第二个参数是右操作数。而这里悄咪咪藏着一个this指针。

        因此调用的时候就不能就不能按这样子了,那怎么调用呢。

int main()
{
	Date d1(2023, 4, 22);
	/*cout << d1;*/
	d1.operator<<(cout);
	d1 << cout;
	return 0;
}

这可不对劲,正常流输入是cout<<d1,这可怎么办才好。很显然我们要消除this指针的影响,同时还能访问其类的内部成员,而友元就可以做到这样子的事情。一步到位,既不像全局函数的访问权限受限制,还可以直接直接消除this指针

友元函数

        友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明的时候加上 friend 关键字

        

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin,Date& d);
public:
	Date(int year= 1970, int month = 1, int day = 1 )
		:_year(year)
		,_month(month)
		,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day << endl;
	return _cout;
}
istream& operator>>(istream& _cin, Date& d)//要修改,别加const
{
	_cin >> d._year >> d._month >> d._day;
	return _cin;
}

int main()
{
	Date d;
	cin >> d;
	cout << d;
	return 0;
}

⚠️注意:

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数。(只是类的朋友)
  • 友元函数不能用const修饰
  • 友元函数可以类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同

友元类

  • 友元类的所有成员函数都是其friend友元所在声明类的友元函数,都可以访问另一个类的公有成员。
  • 友元的关系不能传递,若如果B是A的友元,C是B的友元,则不能说明C是A的友元。
  • 友元不能继承,关于继承的详细讲解在后面博客文章阐述,这里不展开讲解。

定义一个友元类

class Date;   // 前置声明
 
class Time 
{
	friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}
 
private:
	int _hour;
	int _minute;
	int _second;
};
 
class Date 
{
public:
	Date(int year = 1970, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
 
	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问Time类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
 
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

        也就是说这种访问是单向的,时间类里不能访问日期类,因为这是 "单向好友",要想互相访问,只需要互相为各自的友元就好啦。

⚠️注意:

        友元提供了一种突破封装的方式,有时候提供了便利。但是友元会增加耦合度,破坏了特定的封装,所以友元不宜多用。

内部类

        内部类顾名思义就是一个类内部的类。即一个类如果定义在一个类的内部,这个类就叫做内部类。内部类是一个独立的类。它不属于外部内,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

        内部类就是外部类的友元类,参见友元的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员,但这种是绝对单向的友元,外部类不是内部类的友元。

特性:

  • 内部类可以定义在外部的public,protected,private都是可以的
  • 内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名
  • sizeof()外部类=外部类,和内部类没有任何关系

其实这里的概念我们结合友元类就能清晰理解,内部类是外部类的天生友元。

class A {
private:
	static int _s_a1;
	int _a2;
public:
	class B 
	{
		// B天生就是A的友元
	public:
		void foo(const A& a) 
		{
			cout << _s_a1 << endl;  
			cout << a._a2 << endl;  
		}
	private:
		int _b1;
	};
};

        但是需要着重理解的一点是,在写代码的时候看似是外部包含内部的关系,但是实际上以权限的角度来讲,内部权限大于外部,即内包外。要从权限这点抽象的去理解,而非看见的写代码时候的包含关系。

class A {
private:
    static int _s_a1; 
    int _a2;
 
public:
    class B {  // B天生就是A的友元
        friend class A;  // 声明A是B的友元
    private:
        int _b1;
    };
};

我们也可以通过以上的方式去实现打破这种封装,不过情况很少,既然这样子为何不使用一个类呢(除非特定情况)。

再度理解类和对象

        类和对象是面向对象编程(Object-Oriented Programming,简称OOP)中的两个重要概念,用于组织和管理代码,使其更易于理解、维护和扩展。

        类(Class) 可以看作是一张图纸或模板。假设你要建造一栋房子,你需要一张建筑图纸来指导建筑师和工程师。这张图纸就像一个类,它包含了房子的设计、规格和特点。图纸上可能包括了房子的形状、大小、门窗的位置等信息,就像一个类包含属性和方法的定义。

        对象(Object) 则就是按照那张图纸建造出来的实际房子。当你按照图纸建造房子时,你实际上是在基础上创建了一个具体的、独立的实体。这个实际的房子就像类的对象,它有自己的属性(如颜色、材料、装饰)和可以执行的操作(如打开门、关上窗户),但它们都基于同一张图纸创建。

        举个更具体的例子,想象一个类是"汽车",它的属性包括颜色、品牌和速度,方法包括启动、加速和刹车。当你购买一辆具体的车,比如一辆红色的福特(Ford),你就得到了一个对象,这个对象就是这个类的一个实例,拥有红色的颜色、福特的品牌,以及能够启动、加速和刹车等方法。

        所以,类就像是一个设计图纸,对象就像是根据这个图纸建造出来的实际物体。图纸定义了如何制造物体,而物体是根据图纸的规格制造的。类定义了对象的结构和行为,而对象则是类的具体实例,具有自己的属性值,可以执行类中定义的方法。这是面向对象编程的核心概念之一,它有助于将代码组织成更加模块化、可维护和可重用的部分。


总结

在C++类和对象的三个篇章中,主要涉及了C++中类和对象的一系列知识点,包括:

  1. 构造函数和析构函数

  2. 拷贝构造函数

  3. 赋值运算符重载

  4. const成员函数

  5. 初始化列表

  6. static成员

  7. 友元函数和友元类

  8. 内部类

        在本篇文章中,完结了关于C++类和对象的重要知识点。类和对象是面向对象编程的核心,通过构造函数、析构函数、拷贝构造函数等,我们可以创建对象并初始化其属性。静态成员允许类级别的属性和方法,友元函数和友元类提供了访问私有成员的机制,而内部类允许在类内部定义嵌套的类。

        这些知识点为理解和应用C++中的面向对象编程提供了基础。虽然这些概念可能看起来复杂,但它们有助于将代码组织成更模块化、可维护和可重用的部分。相信大家通过不断学习和实践,可以更好地掌握C++编程的技能,并编写更高效、可维护的代码。


    作者水平有限,如有错误欢迎指正!


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

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

相关文章

Compose 如何配置布局?

Compose 是一个界面工具包&#xff0c;可让您轻松实现应用的设计。您只需描述自己想要的界面外观&#xff0c;Compose 会负责在屏幕上进行绘制。 Compose布局的优势 使用Compose布局还有许多其他优势&#xff1a; 灵活性&#xff1a;Compose布局支持组合任何数量的UI元素和自…

代码随想录算法训练营第三十八天丨 动态规划part01

动态规划理论基础 动态规划刷题大纲 什么是动态规划 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的&a…

TypeScript之接口

一、是什么 接口是一系列抽象方法的声明&#xff0c;是一些方法特征的集合&#xff0c;这些方法都应该是抽象的&#xff0c;需要由具体的类去实现&#xff0c;然后第三方就可以通过这组抽象方法调用&#xff0c;让具体的类执行具体的方法 简单来讲&#xff0c;一个接口所描述…

python采集电商jd app搜索商品数据(2023-10-30)

一、技术要点&#xff1a; 1、cookie可以从手机app端用charles抓包获取&#xff1b; 2、无需安装nodejs&#xff0c;纯python源码&#xff1b; 3、搜索接口为&#xff1a;functionIdsearch&#xff1b; 4、clientVersion "10.1.4"同时也支持更高的版本&#xff1b; …

[UDS] --- CommunicationControl 0x28

1 0x28功能描述 根据ISO14119-1标准中所述&#xff0c;诊断服务28服务主要用于网络中的报文发送与接受&#xff0c;比如控制应用报文的发送与接收&#xff0c;又或是控制网络管理报文的发送与接收&#xff0c;以便满足一定场景下的应用需求。 2 0x28应用场景 一般而言&#…

刷穿力扣(31~60)

更好的阅读体验 \huge{\color{red}{更好的阅读体验}} 更好的阅读体验 31. 下一个排列 排列原理就是 C 中的 next_permutation 函数&#xff0c;生成指定序列的下一个全排列从给定序列的最右端开始&#xff0c;找到第一个满足 nums[i] < nums[i 1] 的元素 nums[i]若找不到这…

pytorch 入门 (五)案例三:乳腺癌识别-VGG16实现

本文为&#x1f517;小白入门Pytorch内部限免文章 &#x1f368; 本文为&#x1f517;小白入门Pytorch中的学习记录博客&#x1f366; 参考文章&#xff1a;【小白入门Pytorch】乳腺癌识别&#x1f356; 原作者&#xff1a;K同学啊 在本案例中&#xff0c;我将带大家探索一下深…

高压放大器在工作中的应用实例有哪些

高压放大器是一种电子设备&#xff0c;主要用于将输入的低电压信号放大为输出的高电压信号。它在工业、医疗、科研等领域具有广泛的应用。下面将列举一些高压放大器在工作中的应用实例&#xff1a; 1.高压发生器&#xff1a;高压放大器在高压发生器中被广泛使用。这些发生器通常…

Android渲染流程

目录 缓冲区的不同生命周期代表当前缓冲区的状态&#xff1a; 多个源 ViewRootImpl&#xff1a; Android4.0&#xff1a; Android5.0&#xff1a; Android应用程序调用SurfaceFliger将测量&#xff0c;布局&#xff0c;绘制好的Surface借助GPU渲染显示到屏幕上。 一个Acti…

Cannot find namespace ‘NodeJS‘.

最近在使用自定义指令做防抖节流的时候&#xff0c;使用ts定义定时器类型的时候报的错误&#xff0c;记录一下&#xff1a; 解决方法&#xff1a; 在根目录下找到env.d.ts&#xff0c;或者在根目录中新建一个文件&#xff08;global..d.ts&#xff09;在文件中导出NodeJS命名空…

OpenLayers入门,OpenLayers从vue的assets资源路径加载TopoJson文件并解析数据叠加到地图上,以加载世界各国边界为例

专栏目录: OpenLayers入门教程汇总目录 前言 本章以加载世界各国边界的TopoJson格式数据为例,讲解如何使用OpenLayers从vue的assets资源路径加载TopoJson文件并解析数据叠加到地图上。 GeoJson介绍 GEOJSON是gis地图中常用的数据格式,制作地图时用于存储各种地理数据,使…

使用 node.js 简单搭建Web服务 使用node简单搭建后端服务 使用node搭建服务

使用 node.js 简单搭建Web服务 使用node简单搭建后端服务 使用node搭建服务 1、初始化项目2、安装 Express.js Web 服务框架3、创建 app.js 主入口文件, 并且实现 GET、POST请求4、启动服务5、请求测试 1、初始化项目 例如项目名为 node-server-demo mkdir node-server-demo进…

sd 模型笔记之 SDXL

C站有个创作者Copax&#xff0c;他创作了许多模型和LoRA&#xff0c;其中有一个SDXL1.0的模型非常受欢迎&#xff0c;叫Copax TimeLessXL。 TimeLess的字面意思是永恒&#xff0c;不过有一首英文歌也是TimeLess&#xff0c;歌词大意是唯爱永恒。 这个SDXL1.0的模型更新到了8…

Azure机器学习 - 使用与Azure集成的Visual Studio Code实战教程

本文介绍如何启动远程连接到 Azure 机器学习计算实例的 Visual Studio Code。 借助 Azure 机器学习资源的强大功能&#xff0c;使用 VS Code 作为集成开发环境 (IDE)。 在VS Code中将计算实例设置为远程 Jupyter Notebook 服务器。 关注TechLead&#xff0c;分享AI全维度知识。…

从历史的探索到RFID固定资产管理的未来

在人类历史上&#xff0c;技术的进步一直是推动社会和工业发展的关键因素。其中&#xff0c;RFID技术的出现是一个重要的里程碑。让我们回顾一下RFID技术的历史&#xff0c;并探讨如何将其应用于固定资产管理&#xff0c;为企业提供更高效、智能的解决方案。 RFID&#xff08;R…

开发一个简单的管理系统,前端选择 Vue 还是 React?

目录 比于React&#xff0c;我更喜欢使用Vue 低代码平台的前端框架采用Vue的优势有哪些&#xff1f; JNPF-Web-Vue3 的技术栈介绍 &#xff08;1&#xff09;Vue3.x &#xff08;2&#xff09;Vue-router4.x &#xff08;4&#xff09;Ant-Design-Vue3.x &#xff08;5&#xf…

安装pip install pointnet2_ops_lib/.

安装这个的时候一直报错 总结原因还是版本不一致的问题&#xff0c;参考的博客https://blog.csdn.net/weixin_45144684/article/details/132525431 最后在这个链接里面https://anaconda.org/nvidia/cuda-toolkit成果安装11.5的粗大tookit就成功了&#xff0c; 最后附上所有包的…

大数据-Storm流式框架(七)---Storm事务

storm 事务 需求 storm 对于保证消息处理&#xff0c;提供了最少一次的处理保证。最常见的问题是如果元组可以被 重发&#xff0c;可以用于计数吗&#xff1f;不会重复计数吗&#xff1f; strom0.7.0 引入了事务性拓扑的概念&#xff0c;可以保证消息仅被严格的处理一次。因此可…

JMeter的使用,傻瓜式学习【上】

目录 前言 1、JMeter元件及基本使用作用域&#xff08;简述&#xff09; 1.1、基本元件 1.2、作用域的原则 1.3、元件执行顺序 2、JMeter三个重要组件 2.1、线程组 案例&#xff1a; 2.2、HTTP请求 2.3、查看结果树 响应体中&#xff0c;中文乱码解决方案&#xff1…

python爬虫—使用xpath方法进行数据解析

1. 背景信息 爬取安居客二手房源信息 URL地址&#xff1a;https://wuhan.anjuke.com/sale/?fromnavigation 2. 代码实现 import requests from lxml import etreeif __name__ __main__:# 1.指定URLurl "https://wuhan.anjuke.com/sale/?fromnavigation"# 2.U…