C++_类和对象(下)

news2025/4/7 19:57:36

【本节目标】

  • 再谈构造函数
  • Static成员
  • 友元
  • 内部类
  • 匿名对象
  • 拷贝对象时的一些编译器优化
  • 再次理解封装

1. 再谈构造函数

1.1 构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

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

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

1.2 初始化列表

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

代码演示:

在这里插入图片描述

输出结果:

在这里插入图片描述

这段代码主要是对一些必须要初始化的成员进行初始化操作,且通过调用成员函数实现对外面的变量进行修改的操作。

初始化列表:

初始化列表是在构造函数的参数列表之后,函数体之前,使用冒号 : 分隔,用于对类的成员变量进行初始化。

特点:

  • 初始化时机: 初始化列表是在对象创建时就对成员变量进行初始化,即在对象的内存分配完成后,立即调用成员变量的构造函数进行初始化。
  • 效率较高: 对于一些类型,如 const 成员变量、引用成员变量,必须使用初始化列表进行初始化。而且对于自定义类型的成员变量,使用初始化列表可以避免一次默认构造和一次赋值操作,提高效率。

构造函数的函数体:

构造函数的函数体是在初始化列表之后执行的代码块,用于对成员变量进行赋值操作。

特点:

  • 赋值时机: 构造函数的函数体是在成员变量已经完成初始化(默认初始化或使用初始化列表初始化)之后执行的,因此是一种先创建后赋值的操作。
  • 适用场景: 适用于需要在构造对象时进行一些额外的计算或逻辑处理,然后再对成员变量进行赋值的情况。

注:拷贝构造同样也有初始化列表


拓展_1:

在这里插入图片描述

在同时有缺省参数和传递构造函数参数的时候,会优先使用传递的参数进行初始化。


拓展_2:

在这里插入图片描述

注:单参数构造函数的隐式类型转换
A a = i ;
老版本:首先对i进行调用构造函数创建一个临时的类对象,再将这个对象浅拷贝给类对象a的一个过程。
新版本:编译器进行优化,对a进行直接初始化。


拓展_3:

在这里插入图片描述

代码解释:

  1. 临时对象的创建: 当执行 const A& ref = 5; 时,常量数字 5 作为参数调用 A 的构造函数 A(int i),创建了一个 A 类型的临时对象。这个临时对象是右值,因为它没有一个具体的、持久的名称,并且在表达式结束后原本会被销毁。

  2. 常量左值引用绑定临时对象: const A& ref 是一个常量左值引用,它可以绑定到这个临时对象上,并且将临时对象的生命周期延长到和 ref 的生命周期一致。所以,在 ref 的作用域内,我们可以通过 ref 安全地访问临时对象的成员函数,如 ref.print()。


拓展_4:

在这里插入图片描述

在单参数的基础上,多参数的传参加上了花括号进行区分。


拓展_5:

在这里插入图片描述


拓展_6:

在 C++ 中,成员函数调用时:

同类对象调用: 若形参为 const A&,因同类不同对象可互访成员,仍能访问该对象成员。

不同类对象调用: 当形参是 const A&,被调用的 A 类成员函数需为 const 成员函数,以确保调用时权限一致,避免修改 const 对象状态。

易混淆重点:

  1. 不同类调用时,若以 const 引用接收对象,调用其成员函数,无论有无返回值,都需该函数为 const 成员函数以确保权限一致。

注:const对象只能调用const函数成员

案例演示:

在这里插入图片描述


拓展_7:

在这里插入图片描述

产生后果:

在这里插入图片描述

注:头文件中两个不同类如果后续在声明中需要调用,则需要注意先后顺序。

初始化列表和函数体内赋值混合使用场景:

在这里插入图片描述

【注意】

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

  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:

  • const 成员变量: const 成员变量在初始化后不能再被赋值,因此必须在初始化列表中进行初始化。
  • 引用成员变量: 引用必须在定义时进行初始化,因此也必须在初始化列表中进行初始化。
  • 没有默认构造函数的类类型成员变量: 如果类的成员变量是一个没有默认构造函数的类类型,那么必须在初始化列表中显式调用该类的构造函数进行初始化。
  1. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,
    一定会先使用初始化列表初始化。

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

课堂练习:

class A
{
public:
 	A(int a)
    	:_a1(a)
    	,_a2(_a1)
    	{}
    	
 	void Print() 
 	{
		cout<<_a1<<" "<<_a2<<endl;
    }
    
private:
 	int _a2;
 	int _a1;
};
 
int main() 
{
 	A aa(1);
 	aa.Print();
}

A. 输出1  1
B.程序崩溃
C.编译不通过
D.输出1  随机值  --> 正确

1.3 explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用。

class Date
{
public:
 	// 1. 单参构造函数,没有使用explicit修饰,具有类型转换作用
	// explicit修饰构造函数,禁止类型转换---explicit去掉之后,代码可以通过编译
	explicit Date(int year)
 		:_year(year)
 		{}
 	
 	// 2. 虽然有多个参数,但是创建对象时后两个参数可以不传递
 	//没有使用explicit修饰,具有类型转换作用
	// explicit修饰构造函数,禁止类型转换
	explicit Date(int year, int month = 1, int day = 1)
 		: _year(year)
 		, _month(month)
 		, _day(day)
 		{}
 
 	Date& operator=(const Date& d)
 	{
 		if (this != &d)
 		{
 			_year = d._year;
 			_month = d._month;
 			_day = d._day;
 		}
 		return *this;
 	}
 	
private:
 	int _year;
 	int _month;
 	int _day;
 };
 
void Test()
{
 	Date d1(2022);
 	// 用一个整形变量给日期类型对象赋值
	// 实际编译器背后会用2023构造一个无名对象,最后用无名对象给d1对象进行赋值
	d1 = 2023;
 	// 将1屏蔽掉,2放开时则编译失败,因为explicit修饰构造函数,禁止了单参构造函数类型转换的作用
}

用explicit修饰构造函数,将会禁止构造函数的隐式转换。

2. static成员

2.1 概念

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

面试题:实现一个类,计算程序中创建出了多少个类对象。

在这里插入图片描述

注:如果声明和定义分开,则静态成员需要在定义中声明。

输出结果:

在这里插入图片描述

注:静态函数才能去调用静态成员


通过各种形式访问public静态成员:

在这里插入图片描述

静态成员核心特性:

  1. 类级作用域: 属于类本身而非实例,所有对象共享唯一副本
  2. 内存独立: 存储于静态存储区(全局 / 静态区),生命周期与程序同步

访问方式:

    • 推荐: 类名::成员名(编译期绑定)
    • 允许: 对象名.成员名 或 指针->成员名(即使指针为空)
    • 原理: 不依赖对象实例,通过类元信息直接寻址

注: 类外面不可以访问private权限成员。

示例:

class MyClass {
public:
    static int s_val;  // 声明
    static void s_func() { /* ... */ }
};

int MyClass::s_val = 0;  // 必须类外初始化

int main() {
    MyClass* ptr = nullptr;
    ptr->s_val = 42;    // 合法,空指针访问静态成员
    MyClass::s_func();  // 更安全的访问方式
}

问:当我们将静态成员放入private权限时,该通过什么办法拿到静态成员数据

我们可以通过静态成员函数,在静态成员函数内调用静态成员变量,这样我们就可以通过类在外面访问静态成员函数拿到静态成员变量的数据。

示例:

在这里插入图片描述

画图详解:

在这里插入图片描述

拓展_1:

在这里插入图片描述

静态成员函数中不能访问非静态成员变量(只允许访问静态成员变量),因为静态成员函数没有this指针,所以无法指向对象类的私有成员。


拓展_2:

当我们不能使用关键字的情况下如何实现:1+2+…+n?

示例:

在这里插入图片描述

通过创建装有n个元素的Sum自定义类型数组,就可以调用n次构造函数,实现累加效果。

2.2 特性

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

3. 友元

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

友元分为:友元函数友元类

3.1 友元函数

问题:现在尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。 this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。

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

// d1 << cout; -> d1.operator<<(&d1, cout);  不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧
	ostream& operator<<(ostream& _cout)
 	{
 		_cout << _year << "-" << _month << "-" << _day << endl;
 		return _cout;
 	}
private:
 	int _year;
 	int _month;
 	int _day;
 };

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

class Date
{
 	friend ostream& operator<<(ostream& _cout, const Date& d);
 	friend istream& operator>>(istream& _cin, Date& d);
public:
 	Date(int year = 1900, 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;
 	return _cout;   
}

istream& operator>>(istream& _cin, Date& d)
{
 	_cin >> d._year;
 	_cin >> d._month;
 	_cin >> d._day;
 	return _cin;
}

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

注:
接收参数需要严格符合类型对齐要求
比如:cout << d1 --> 接收形参:ostream& _cout, const Date& d。

【注意】

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

友元函数对比普通函数核心区别在于友元函数接受的指定类可以访问private权限成员。

3.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

  • 友元关系是单向的,不具有交换性。
    比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接
    访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

  • 友元关系不能传递
    如果C是B的友元, B是A的友元,则不能说明C时A的友元。

  • 友元关系不能继承,在继承位置再给大家详细介绍。

class Time
{
    friend class Date;
    // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:
    Time(int hour = 0, int minute = 0, int second = 0)
        : _hour(hour)
        , _minute(minute)
        , _second(second)
    {}
    void Print_time()
    {
        cout << _hour << "/" << _minute << "/" << _second << endl;
    }
private:
    int _hour;
    int _minute;
    int _second;
};

class Date
{
public:
    Date(int year = 2025, int month = 2, int day = 28)
        :_year(year)
        , _month(month)
        , _day(day)
        , _t(21, 29, 10)
    {}
    void Print()
    {
        _t.Print_time();
        cout << _year << "/" << _month << "/" << _day << " - " <<
            _t._hour << "/" << _t._minute << "/" << _t._second << endl;
    }
private:
    int _year;
    int _month;
    int _day;
    Time _t;
};

int main()
{
    Date d;
    d.Print();
    return 0;
}

【注意】

友元类和普通类的区别:

访问权限:

  • 普通类: 只能访问其他类的public成员,遵循封装原则,保证数据安全。
  • 友元类: 可访问授权类的所有成员,包括privateprotected成员,打破封装限制。

关系性质:

  • 普通类: 类间相对独立,通过公共接口交互。
  • 友元类: 与授权类存在特殊信任关系,关系单向,破坏一定封装性。

代码维护:

  • 普通类: 封装性好,修改内部实现通常不影响其他类,可维护性高。
  • 友元类: 授权类成员变化可能影响友元类,耦合度高,维护较复杂。

4. 内部类

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

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

特性:

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

计算类大小:

在这里插入图片描述

输出结果:

在这里插入图片描述

注: B类受A类域和访问限定符的限制,其实他们是两个独立的类。


如何定义B类:

在这里插入图片描述

当我们的内部类处于private权限时,我们通过以下办法定义B类:

在这里插入图片描述

通过内部类概念实现:1+2+…n的计算:

在这里插入图片描述

输出结果:

在这里插入图片描述

4.1 内部类在 public 权限下的核心特性

  1. 可见性与创建
  • 内部类在public权限下对外部完全可见,可通过Outer::Inner直接创建对象。
  • 外部类成员函数可直接使用内部类名创建对象(无需类作用域限定符)。

示例:

在这里插入图片描述

  1. 成员访问规则
  • 内部类→外部类
    • 内部类可直接访问外部类的public/protected/private成员(嵌套作用域特权)。

注:前提是内部类成员函数接收外部类类型。

    • 访问非静态成员需通过外部类对象 / 引用 / 指针传递。

  • 外部类→内部类

    • 外部类成员函数内通过实例化内部类对象可自由访问内部类的public成员,若内部类成员为private,需通过friend声明授权。
  1. 参数传递的注意事项
  • 内部类成员函数若需调用外部类的非const成员,形参必须为非const引用 / 指针(如Outer&)。

  • 若仅需调用const成员,可使用const Outer&,但此时无法修改外部类对象。

  1. 静态成员的访问
  • 内部类的静态成员可通过Outer::Inner::StaticMember直接访问,无需创建对象。

注:如果静态成员为private权限,则受类规则限制,我们不能直接进行访问,我们可以通过定义静态成员函数返回静态成员变量。


4.2 内部类在 private 权限下的核心特性

示例:

在这里插入图片描述

  1. 可见性限制
  • 外部不可见: 内部类的可见性是由public或者private权限决定的,所以private权限的内部类无法被外部直接访问或实例化。

  • 封装性: 内部类的实现细节完全隐藏,外部代码只能通过外部类的公共接口间接使用内部类。

  1. 访问关系(容易混淆)
  • 外部类对于内部类的访问依旧受制于访问权限,可以访问内部类的public权限下的成员,private权限的成员变量则需要通过外部类调用内部类自身public权限下成员函数才能间接访问

  • 内部类可以类比是外部类天然的友元类但外部类并不是内部类的友元),可以直接调用外部类的各个权限下的成员变量或者成员函数。但本质上内部类能特殊访问外部类是源自于它是外部类的成员类。

  • 若内部类声明为static,则无法直接访问外部类的非静态成员(需通过对象访问)。

  1. 静态成员的特殊规则
  • private以及public权限下的内部类可以访问外部类的静态成员变量或者函数,因为静态成员变量以及函数是属于类的并不是属于对象,所以对于内部类来说都可以通过类名+作用域限定符号进行访问。

注: 内部类也可以可直接访问外部类静态成员,如同访问自身成员。并不一定需要显示访问。

  • 不过,普通类不能直接通过 “类名 + 作用域限定符” 的方式去访问另一个类中 private 权限下的静态成员,仍然要遵循类的访问权限规则。也就是说,只有类自身以及它的友元(友元类或者友元函数)才可以访问这些 private 权限的静态成员。

总结:

将内部类声明为 private`是 C++ 中实现封装的重要手段,它通过限制可见性和控制访问权限,确保外部类的接口简洁性,并将内部类的实现细节完全隐藏。这种设计尤其适用于工具类、辅助类或仅服务于外部类的底层逻辑。

  • 同类对象可以自由访问彼此的私有成员(包括变量和函数),这是 C++ 封装性的体现。

  • 外部代码无法直接访问私有成员 ,必须通过类的 public 接口或友元机制。

对比:

从宏观设计角度来看:将 ​private 内部类视为外部类的“子成员”​,而 ​public 内部类视为“独立但关联的组件”​


5. 匿名对象

class A
{
public:
 	A(int a = 0)
 	:_a(a)
 	{
 		cout << "A(int a)" << endl
 	}
 	~A()
 	{
 		cout << "~A()" << endl;
 	}
private:
 	int _a;
};

class Solution {
public:
 	int Sum_Solution(int n) 
 	{
 		//...
 		return n;
 	}
 };
 
 int main()
 {
 	A aa1;
 	// 不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义
	//A aa1();
 	// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,
	// 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数
	A();
 	A aa2(2);
 	// 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说
	Solution().Sum_Solution(10);
 	return 0;
 }

6. 编译器优化

class A
{
public:
 	A(int a = 0)
 		:_a(a)
 	{
 		cout << "A(int a)" << endl;
 	}
 	
 	A(const A& aa)
 		:_a(aa._a)
 	{
 		cout << "A(const A& aa)" << endl;
 	}
 	
 	A& operator=(const A& aa)
 	{
 		cout << "A& operator=(const A& aa)" << endl;
 		if (this != &aa)
 		{
 			_a = aa._a;
 		}
 		return *this;
 	}
 	
 	~A()
 	{
 		cout << "~A()" << endl;
 	}
private:
 	int _a;
};

void f1(A aa)
{}

A f2()
{
 	A aa;
 	return aa;
}

int main()
{
 	// 传值传参
	A aa1;
 	f1(aa1);
 	cout << endl;
 	// 传值返回
	f2();
 	cout << endl;
 	// 隐式类型,连续构造+拷贝构造->优化为直接构造
	f1(1);
 	// 一个表达式中,连续构造+拷贝构造->优化为一个构造
	f1(A(2));
 	cout << endl;
 	// 一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造
	A aa2 = f2();
 	cout << endl;
 	// 一个表达式中,连续拷贝构造+赋值重载->无法优化
	aa1 = f2();
 	cout << endl;
 	return 0;
}

示例:

在这里插入图片描述

输出结果:

在这里插入图片描述

在形参上我们使用了实参的拷贝类型,如果我们要使用引用类型的话就会出现问题。

如下报错:

在这里插入图片描述

结论:由于2和3案例中实参是临时变量,一个临时的变量是无法使用引用类型的;如果强行使用引用类型,则需要使用通过const 类名引用进行延长生命周期。


拓展_1:

在这里插入图片描述

通过匿名对象以及缺省参数的使用可以在调用函数的时候不传入任何实参也能调用函数。


拓展_2:

在这里插入图片描述


拓展_3:

在这里插入图片描述


本章完~

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

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

相关文章

Docker设置代理

目录 前言创建代理文件重载守护进程并重启Docker检查代理验证 前言 拉取flowable/flowable-ui失败&#xff0c;用DaoCloud源也没拉下来&#xff0c;不知道是不是没同步。索性想用代理拉镜像。在此记录一下。 创建代理文件 创建docker代理配置 sudo mkdir -p /etc/systemd/s…

一键自动备份:数据安全的双重保障

随着数字化时代的到来&#xff0c;数据已成为企业和个人不可或缺的核心资产。在享受数据带来的便捷与高效的同时&#xff0c;数据丢失的风险也随之增加。因此&#xff0c;备份文件的重要性不言而喻。本文将深入探讨备份文件的重要性&#xff0c;并介绍两种实用的自动备份方法&a…

HeidiSQL:多数据库管理工具

HeidiSQL 是一款广受欢迎的免费开源数据库管理工具&#xff0c;专为数据库管理员及开发者设计。无论您是刚接触数据库领域的新手&#xff0c;还是需要同时处理多种数据库系统的专业开发者&#xff0c;该工具都能凭借其直观的界面和强大的功能&#xff0c;助您轻松完成数据管理任…

医药档案区块链系统

1. 医生用户模块​​ ​​目标用户​​&#xff1a;医护人员 ​​核心功能​​&#xff1a; ​​检索档案​​&#xff1a;通过关键词或筛选条件快速定位患者健康档案。​​请求授权​​&#xff1a;向个人用户发起档案访问权限申请&#xff0c;需经对方确认。​​查看档案​…

蓝桥云客--浓缩咖啡液

4.浓缩咖啡液【算法赛】 - 蓝桥云课 问题描述 蓝桥杯备赛选手小蓝最近刷题刷到犯困&#xff0c;决定靠咖啡续命。他手上有 N 种浓缩咖啡液&#xff0c;浓度分别是 A1​%, A2​%, …, AN​%&#xff0c;每种存货都是无限的。为了提神又不炸脑&#xff0c;小蓝需要按比例混合这…

SQLark(百灵连接):一款面向信创应用开发者的数据库开发和管理工具

SQLark&#xff08;百灵连接&#xff09;是一款面向信创应用开发者的数据库开发和管理工具&#xff0c;用于快速查询、创建和管理不同类型的数据库系统。 目前可以支持达梦数据库、Oracle 以及 MySQL。 SQL 智能编辑器 基于语法语义解析实现代码补全能力&#xff0c;为你提供…

计算机视觉——为什么 mAP 是目标检测的黄金标准

概述 在目标检测领域&#xff0c;有一个指标被广泛认为是衡量模型性能的“黄金标准”&#xff0c;它就是 mAP&#xff08;Mean Average Precision&#xff0c;平均精确率均值&#xff09;。如果你曾经接触过目标检测模型&#xff08;如 YOLO、Faster R-CNN 或 SSD&#xff09;…

Frame Of Reference压缩算法

文章目录 1_概述2_算法基本步骤3_过程优化4_优势以及局限5_模拟实现6_总结 1_概述 Frame of Reference&#xff08;FoR&#xff09;压缩算法 是一种用于压缩数值数据的算法&#xff0c;特别是在处理大规模数据集时&#xff0c;利用数据的局部性和重复性来减少存储和传输的开销…

esp32cam 开发板搭载ov3660摄像头在arduino中调用kimi进行图像识别

首先呢,最近搞一个项目,需要一个摄像头拍摄图片 就买了个ov3660开发板,用的esp32S芯片 淘宝商家给的教程是arduino的,所以先用arduino跑起来 arduino配置esp32-cam开发环境 - 简书1、安装arduino https://www.arduino.cc/en/Main/Software?setlang=cn 2、配置esp32 打开…

二十种中药果实识别分类系统,Python/resnet18/pytorch

二十种中药果实识别分类系统,Python/resnet18/pytorch 基于pytorch训练, resnet18网络&#xff0c;可用于训练其他分类问题&#xff0c;也可自己重新训练 20类中药材具体包括&#xff1a;(1) 补骨脂&#xff0c;(2) 草豆蔻&#xff0c;(3) 川楝子&#xff0c;(4) 地肤子&…

如何实现两个视频融合EasyCVR平台的数据同步?详细步骤指南

有用户咨询&#xff0c;现场需要数据库同步&#xff0c;如何将两个EasyCVR平台的数据进行同步呢&#xff1f; 这篇文章我们将详细介绍如何通过简单的接口调用&#xff0c;高效完成两个平台的数据同步操作。 1&#xff09;获取token 使用Postman调用登录接口&#xff0c;获取…

WindowsPE文件格式入门05.PE加载器LoadPE

https://bpsend.net/thread-316-1-1.html LoadPE - pe 加载器 壳的前身 如果想访问一个程序运行起来的内存,一种方法就是跨进程读写内存,但是跨进程读写内存需要来回调用api,不如直接访问地址来得方便,那么如果我们需要直接访问地址,该怎么做呢?.需要把dll注进程,注进去的代码…

使用Cusor 生成 Figma UI 设计稿

一、开发环境 系统&#xff1a;MacOS 软件版本&#xff1a; Figma&#xff08;网页或APP版&#xff09; 注&#xff1a;最好是app版&#xff0c;网页版figma 没有选项 import from manifest app下载地址&#xff1a;Figma Downloads | Web Design App for Desktops & …

Golang的文件同步与备份

Golang的文件同步与备份 一、Golang介绍 也称为Go语言&#xff0c;是谷歌开发的一种编程语言&#xff0c;具有高效的并发编程能力和出色的内存管理。由于其快速的编译速度和强大的标准库&#xff0c;Golang在网络应用、云平台和大数据等领域得到了广泛应用。 二、文件同步与备份…

如何用人工智能大模型,进行作业批改?

今天我们学习人工智能大模型如何进行作业批改。手把手学习视频请访问https://edu.csdn.net/learn/40402/666452 第一步&#xff0c;进入讯飞星火。打开google浏览器&#xff0c;输入百度地址后&#xff0c;搜索”讯飞星火”&#xff0c;在搜索的结果中&#xff0c;点第一个讯飞…

MATLAB之数据分析图系列 三

三维堆叠柱状图 Bar3StackPlot.m文件 clc; clear; close all; %三维堆叠柱状图 %% 数据准备 % 读取数据 load data.mat % 初始化 dataset X; s 0.4; % 柱子宽度 n size(dataset,3); % 堆叠组数%% 图片尺寸设置&#xff08;单位&#xff1a;厘米&#xff09; figureUnits c…

python爬虫:DrissionPage实战教程

如果本文章看不懂可以看看上一篇文章&#xff0c;加强自己的基础&#xff1a;爬虫自动化工具&#xff1a;DrissionPage-CSDN博客 案例解析&#xff1a; 前提&#xff1a;我们以ChromiumPage为主&#xff0c;写代码工具使用Pycharm&#xff08;python环境3.9-3.10&#xff09; …

一、STM32简介

一、实验器材介绍 二、STM32简介 1.STM32 名词解释 STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ST&#xff0c;指ST公司&#xff08;意法半导体&#xff09;;M&#xff0c;MicroController 微控制器&#xff08;MCU,MicroController Unit 微控制器单元/单片机&…

[ctfshow web入门] web2

前置知识 js是可以写在网页中&#xff0c;用于控制网页行为&#xff0c;例如现在表现出无法使用F12&#xff0c;常见用法校验前台登录时输入的邮箱格式是否正确 ‌view-source‌协议是一种早期就存在的协议&#xff0c;基本上所有主流浏览器都支持这一协议&#xff0c;因此用户…

PyQt5和OpenCV车牌识别系统

有需要请加文章底部Q哦 可远程调试 PyQt5和OpenCV车牌识别系统 一 介绍 此车牌识别系统基于PyQt5和OpenCV开发&#xff0c;蓝牌&#xff0c;新能源(绿牌)&#xff0c;黄牌&#xff0c;白牌均可以准确识别&#xff0c;支持中文识别&#xff0c;可以导出识别结果(Excel格式)。此…