类和对象(一)(C++)

类和对象:

类的引入:

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现, 会发现struct中也可以定义函数

typedef int DataType;
struct Stack
{
	//成员函数
	void Init(size_t capacity)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}
	void Push(const DataType& data)
	{
		// 扩容
		_array[_size] = data;
		++_size;
	}
	DataType Top()
	{
		
			return _array[_size - 1];
	}
	void Destroy()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
	//成员变量
	DataType* _array;
	size_t _capacity;
	size_t _size;
};

但c++更喜欢用class来代替:

类的两种定义方式:

1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内 联函数处理。

2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::,

这些在之后都会经常用到

成员变量命名规则:

class Date
 {
 public:
 void Init(int year)
 {
 // 这里的year到底是成员变量,还是函数形参?
year = year;
 }
 private:
 int year;
 };

为了区分开来,会在成员变量前加_来区分,也可以用其他方式

类的访问限定符:

1.pubic,公有 2.protected,保护 3.private,私有

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

2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)

3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止

4. 如果后面没有访问限定符,作用域就到}即类结束。

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

我们一般对成员变量设为私有,成员函数设为公有

如何计算类的大小:

一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐,成员函数会放在公共的代码段,因为多个对象调用同一份函数,如果按照此种方式存储,当一 个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间

但空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象,即证明这个类存在

class A
{

};
int main()
{
	cout << sizeof(A) << endl;
	return 0;
}

this指针:

特点:

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值

2. 只能在“成员函数”的内部使用

3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针,this存储在栈上

4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传

我们在类中也可以直接使用this指针来更好的理解

void Print()
{
// this = nullptr;
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year; // 年
int _month; // 月
int _day; // 日
};

int main()
{
Date d1;
Date d2;
d1.Init(2024, 4, 2);
d2.Init(2024, 4, 3);
}

this指针可以为空吗?

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

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

以上两个代码,第一个不会报错,第二个报错,原因是第一个没有对this指针解引用,而第二个对this空指针解引用了,会进行报错

空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员 函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数 

类的6个默认成员函数:

1.构造函数:

构造函数的主要任务并不是开空间创建对象,而是初始化对象

特征:

1. 函数名与类名相同。

2. 无返回值。

3. 对象实例化时编译器自动调用对应的构造函数。

4. 构造函数可以重载。

class Date
{
public:
	Date()//无参,打印值默认
	{

	}
	Date(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.Print();
	Date d2(1, 2, 3);
	d2.Print();
	return 0;
}

如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦 用户显式定义编译器将不再生成。

C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类 型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型,对于内置类型,没有规定要不要做处理(部分编译器会处理),对自定义类型才会调用无参构造

但:

C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在 类中声明时可以给默认值

class Time
 {
 private:
 int _hour;
 int _minute;
 int _second;
 };
class Date
 {
 private:
 // 基本类型(内置类型)
 int _year =1;
 int _month = 1;
 int _day = 1;
 // 自定义类型
Time _t;
 };
 int main()
 {
 Date d;
 return 0;
 }

内置类型可处理可不处理,自定义类型会调用默认构造,如果没有,就会报错(可以进行自定义类型的多重嵌套)

无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。 注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。否则会存在使用冲突

2.析构函数

特点:

1. 析构函数名是在类名前加上字符 ~。

2. 无参数无返回值类型。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构 函数不能重载

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

 当没有显式析构函数时,编译器自动生成的析构函数,对内置类型不做处理,自定义类型调用析构函数

class Time
 {
 public:
 ~Time()
 {
 cout << "~Time()" << endl;
 }
 private:
 int _hour;
 int _minute;
 int _second;
 };
 class Date
 {
 private:
 // 基本类型(内置类型)
 int _year = 1970;
 int _month = 1;
 int _day = 1;
 // 自定义类型
Time _t;
 };
 int main()
 {
 Date d;
 return 0;
 }

 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类

 stack::~stack()
 {
	 if (_a) {
		 cout << "Destroy" << endl;
		 _capacity = 0;
		 _top = 0;
		 free(_a);
		 _a = NULL;
	}
 }

3.拷贝构造

 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存 在的类类型对象创建新对象时由编译器自动调用

特点:

1. 拷贝构造函数是构造函数的一个重载形式。

2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。

class Date
{
public:
	void Print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	Date(int year=1,int month=1,int day=1) {
		cout << "构造" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)//防止被修改
	{
		cout << "拷贝" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year=1 ;
	int _month=1;
	int _day=1;
};
int main()
{
	Date d;
	d.Print();
	Date d1=d;//Date d1(d);两者等价
	d1.Print();
	return 0;
}

拷贝构造参数用const 修饰,防止被修改 

为了理解无穷递归,在这里举个例子

void func(Date& d)
{
	d.Print();
}
int main()
{
	Date d2;
		func(d2);
	return 0;
}

这里用引用传递实参和形参都是d2,而值传递的话会先拷贝d2给d,进入到拷贝函数中d2和d地址也不同 

若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请 时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

如stack中的深拷贝:

 stack::stack(const stack& st)
 {
	 _a = (int*)malloc(sizeof(int) * st._capacity);
	 if (_a == nullptr)
	 {
		 return;
	 }
	 _capacity = st._capacity;
	 _top = st._top;
	 memcpy(_a, st._a, _capacity * sizeof(int));//深拷贝
 }//不这样写只是浅拷贝

 4.运算符重载:

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似

函数名字:关键字operator后面接需要重载的运算符符号。

注意:

不能通过连接其他符号来创建新的操作符:比如operator@

作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this

.*   ::   sizeof   ?:   . 注意以上5个运算符不能重载。

 .*很少见,下面给一个场景

class OB
{
public:
	void func()
	{
		cout << "void func()" << endl;
	}
};

typedef void(OB::* PtrFunc)();//成员函数指针类型

int main()
{
	PtrFunc fp = &OB::func;//定义成员函数指针p指向函数func
	OB temp;//定义ob类对象temp
	(temp.*fp)();
	return 0;
}

运算符重载成全局的就需要成员变量是公有的,封装性不能保证。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
//private:
	int _year;
	int _month;
	int _day;
};
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day;
}

 这里先写一个判断日期相等的函数,可以看到,如果写成全局的函数,私有的变量就需要变为公有,所以我们就重载成成员函数 

这里可以用我们用重载成成员函数解决

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
		bool operator==(const Date& d)
	{
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}
//private:
	int _year;
	int _month;
	int _day;
};

赋值运算符重载:

格式:

参数类型:const T&,传递引用可以提高传参效率

返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值 ,检测是否自己给自己赋值

返回*this :要复合连续赋值的含义

对返回值类型进行深究:

传值返回:生成一个拷贝作为返回值

传引用返回:不会拷贝

Date func()
{
	Date d;
	return d;//出作用域析构d
}//传值返回临时对象,具有常性,需要拷贝
int main()
{
	 Date& ref = func();//报错
	 const Date& ref = func();//正确
	return 0;
}

这里使用传值返回, 在func中建立d,返回d的值时会拷贝d的值给一个临时变量,调用拷贝函数,临时变量具有常性,需要const 接收,并且d的值,出函数作用域会调用析构

Date& func()
{
	Date d;
	return d;
}
int main()
{
	Date& ref = func();//ref类似于野指针了,指向的空间可能会改变
	return 0;
}

这里传引用是有问题的,d出作用域就会销毁,再返回其地址类似于野指针了,指向空间可能会改变

但如果改成这样的话,就不会报错了,因为d相当于在全局域了

Date& func()
{
static	Date d;
	return d;
}//可以引用返回

所以总结一下, 

返回对象是局部变量或临时对象,用引用返回存在风险,虽然减少了拷贝
 返回对象是全局变量,用引用就行

  出了作用域,返回对象还在没有析构,那就可以用引用返回,减少拷贝
 a、返回对象生命周期到了,会析构,传值返回
 b、返回对象生命周期没到,不会析构,传引用返回

 连续复制,如果知识两个值进行运算的话,我们是可以将返回类型设为void的,但d1=d2=d3怎么办呢,这个式子从右向左依次赋值,所以返回类型要修改为Date&

			Date& operator=(const Date& d)//void不支持三个数连续等于//传值返回会拷贝构造
	{
				cout << "赋值" << endl;
		if (this != &d)//防止自己给自己赋值
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

5..取地址及const取地址操作符重载 

class A {
public:
	A* operator&()
	{
		return this;
	}
	const A* operator&()const 
	{
		return this;
	}
};
int main()
{
	A a1;
	const A a2;
	cout << &a1<< endl;
	cout << &a2 << endl;
	return 0;
}

这两个函数重载依靠this指针类型的不同,但我们不写编译器会自动生成

日期类的实现:

class Date
{
public:
	friend ostream& operator<<(ostream& out, const Date& d);///ostream抢不过第一个参数形参
	//istream& operator>>(const Date& d);参数问题
		friend istream& operator>>(istream& in,Date& d);
	Date(int year = 1900, int month = 1, int day = 1);
	int CheckDate()
	{
		if (_month > 12 || _month < 1||_day>Get_day(_year,_month))
		{
			cout << "输入错误" << endl;
			return 1;
		}
		else
		{
			return 0;
		}

	}
	void Print();
	int Get_day(int year, int month)
	{
		assert(month > 0 && month < 13);
		static int data[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//多次调用
		if (month==2&&(year%100==0&&year%4!=0||year%400==0))
		{
			return 29;
		}
		return data[_month];
	}
	Date& operator+=(int day);
	Date operator+(int day)const;
	Date& operator-=(int day);
	Date operator-(int day)const;

	Date operator++(int);
	Date operator--(int);
	Date& operator--();
	Date& operator++(); 

	bool operator>(const Date& d)const;
	bool operator>=(const Date& d) const;
	bool operator<=(const Date& d) const;
	bool operator<(const Date& d) const;
	bool operator==(const Date& d) const;
	bool operator!=(const Date& d) const;
	int operator-(const Date& d) const;

private:
	int _year;
	int _month;
	int _day;
};
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
void Date::Print()
{
	cout << _year <<" "<< _month <<" "<< _day << endl;
}
Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		*this-=-day;
		return *this;
	}
	_day += day;
	while (_day > Get_day(_year, _month))
	{
		_day -= Get_day(_year, _month);
		_month++;
		if (_month == 13)
		{
			_month = 1;
			_year++;
		}
	}
		return *this;
}
Date Date::operator+(int day) const
{
	Date tmp = *this;
	tmp += day;
	return tmp;
}
Date& Date::operator-=(int day) 
{
	if (day < 0)
	{
		*this += -day;
		return *this;
	}
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			_month = 12;
			_year--;
		}
		_day += Get_day(_year, _month);
	}
	return *this;
}
Date Date::operator-(int day) const
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}
Date Date::operator++(int)
{
	Date tmp = *this;
	(*this) += 1;
	return tmp;
}
Date Date::operator--(int)
{
	Date tmp = *this;
	(*this)-=1;
	return tmp;
}
Date& Date::operator--()
{
	(*this) -= 1;
	return *this;
}
Date& Date::operator++()
{
	(*this) += 1;
	return *this;
}
bool Date::operator>(const Date & d) const 
{
	if (_year> d._year)
	{
		return true;
	}
	else if (_year == d._year)
	{
		if (_month > d._month)
		{
			return true;
		}
		else if (_month == d._month)
		{
			if (_day > d._day)
			{
				return true;
			}
		}
	}
		return false;
}
bool Date::operator>=(const Date& d) const
{
	return *this == d || *this > d;
}
bool Date::operator<=(const Date& d)const
{
	return !(*this > d);
}
bool Date::operator<(const Date& d)const
{
	return !(*this >= d);
}
bool Date::operator==(const Date & d)const
	{
		return _year == d._year && _month == d._month && _day == d._day;
	}
bool Date::operator!=(const Date & d)const
	{
		return !(*this == d);
	}
int Date:: operator-(const Date& d)const//算有多少天
{
	Date big = *this;
 Date small = d;//拷贝构造
 int flag = 1;
	 if (big < small)
	 {
		 big = d;
		 small = *this;
		 flag = -1;
	 }
	 int n = 0;
	 while (small < big)
	 {
		 small++;
		 n++;
	 }
	 return n*flag;
}
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year <<" "<< d._month <<" "<< d._day << endl;
	return out;
}
istream& operator>>(istream& in, Date& d)//传引用,不支持拷贝构造,被禁用了
{
		cout << "请输入年月日" << endl;
		in >> d._year >> d._month >> d._day;
		if (d.CheckDate())
		{
			cout << "日期非法" << endl;
       }
	return in;
}

 日期类的实现有一些需要注意的点,我在这里一一说明:

1.对于多次调用的Get_day函数,我们直接在类中展开写,其会自动转化为内联函数,包括data数组,我们也要多次使用,所以在前面加上static修饰,变为全局变量

2.对于*this不能改变的函数,我们在函数声明后加上const修饰(比较特殊),可以发现,传引用返回并且对*this进行操作的一般不加const修饰

3.前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载 , C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器 自动传递

4.cout和cin无法对自定义成员进行处理,进行运算符重载要将其转化为友元类才符合输出格式(重载为全局破坏封装性,重载为成员函数(不是友元)输出格式不符合,第一个参数为this形参,不能是cout或cin)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第123题买卖股票的最佳时机III

题目&#xff1a; 题解&#xff1a; class Solution {public int maxProfit(int[] prices) {int n prices.length;int buy1 -prices[0], sell1 0;int buy2 -prices[0], sell2 0;for (int i 1; i < n; i) {buy1 Math.max(buy1, -prices[i]);sell1 Math.max(sell1, b…

Docker最新超详细版教程通俗易懂

文章目录 一、Docker 概述1. Docker 为什么出现2. Docker 的历史3. Docker 能做什么 二、Docker 安装1. Docker 的基本组成2. 安装 Docker3. 阿里云镜像加速4. 回顾 hello-world 流程5. 底层原理 三、Docker 的常用命令1. 帮助命令2. 镜像命令dokcer imagesdocker searchdocker…

【C++ 初阶】内联函数 inline 与 宏定义的区别!

文章目录 1. 内联函数2. 内联函数和宏定义的区别3. 宏函数4. 宏的优缺点5. 小扩展 1. 内联函数 &#x1f34e; 概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序…

RabbitMQ三、springboot整合rabbitmq(消息可靠性、高级特性)

一、springboot整合RabbitMQ&#xff08;jdk17&#xff09;&#xff08;创建两个项目&#xff0c;一个生产者项目&#xff0c;一个消费者项目&#xff09; 上面使用原生JAVA操作RabbitMQ较为繁琐&#xff0c;很多的代码都是重复书写的&#xff0c;使用springboot可以简化代码的…

十_信号3-可重入函数

如上图所示链表&#xff0c;在插入节点的时候捕获到了信号&#xff0c;并且该信号的自定义处理方式中也调用了插入节点的函数。 在main函数中&#xff0c;使用insert向链表中插入一个节点node1&#xff0c;在执行insert的时&#xff0c;刚让头节点指向node1以后(如上图序号1)&…

④单细胞学习-cellchat细胞间通讯

目录 1&#xff0c;原理基础 流程 受体配体概念 方法比较 计算原理 2&#xff0c;数据 3&#xff0c;代码运行 1&#xff0c;原理基础 原文学习Inference and analysis of cell-cell communication using CellChat - PMC (nih.gov) GitHub - sqjin/CellChat: R toolk…

算法-找出N个数组的共同元素

一、代码与执行结果 财经新闻是大众了解金融事件的重要渠道&#xff0c;现有N位编辑&#xff0c;分别对K篇新闻进行专业的编辑与排版。需要您找出被这N位编辑共同编辑过的新闻&#xff0c;并根据这些新闻ID升序排列返回一个数组。 import random# 查找编辑共同处理的新闻id def…

测试基础09:缺陷(bug)生命周期和缺陷(bug)管理规范

课程大纲 1、缺陷&#xff08;bug&#xff09;生命周期 2、缺陷&#xff08;bug&#xff09;提交规范 2.1 宗旨 简洁、清晰、可视化&#xff0c;减少沟通成本。 2.2 bug格式和内容 ① 标题&#xff1a;一级功能-二级功能-三级功能_&#xff08;一句话描述bug&#xff1a;&…

eNsp——两台电脑通过一根网线直连通信

一、拓扑结构 二、电脑配置 ip和子网掩码&#xff0c;配置两台电脑处于同一网段 三、测试 四、应用 传文件等操作&#xff0c;可以在一台电脑上配置FTP服务器

含情脉脉的进程

冯诺依曼体系结构 一个计算机在工作的时候是怎样的呢&#xff1f; 我们所认识的计算机都是由一个个的硬件组件组成&#xff1a; 输入设备&#xff1a;键盘、鼠标、摄像头、话筒、磁盘、网卡 中央处理器&#xff08;CPU&#xff09;&#xff1a;运算器、控制器 输出设备&#x…

Java多线程(04)—— 保证线程安全的方法与线程安全的集合类

一、CAS 与原子类 1. CAS CAS&#xff08;compare and swap&#xff09;&#xff0c;是一条 cpu 指令&#xff0c;其含义为&#xff1a;CAS(M, A, B); M 表示内存&#xff0c;A 和 B 分别表示一个寄存器&#xff1b;如果 M 的值和 A 的值相同&#xff0c;则把 M 和 B 的值交…

我成功创建了一个Electron应用程序

1.创建electron项目命令&#xff1a; yarn create quick-start/electron electron-memo 2选择&#xff1a;√ Select a framework: vue √ Add TypeScript? ... No √ Add Electron updater plugin? ... Yes √ Enable Electron download mirror proxy? ... Yes 3.命令&a…

渲染100为什么是高性价比网渲平台?渲染100邀请码1a12

市面上主流的网渲平台有很多&#xff0c;如渲染100、瑞云、炫云、渲云等&#xff0c;这些平台各有特色和优势&#xff0c;也都声称自己性价比高&#xff0c;以渲染100为例&#xff0c;我们来介绍下它的优势有哪些。 1、渲染100对新用户很友好&#xff0c;注册填邀请码1a12有3…

09.责任链模式

09. 责任链模式 什么是责任链设计模式&#xff1f; 责任链设计模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;它允许将请求沿着处理者对象组成的链进行传递&#xff0c;直到有一个处理者对象能够处理该请求为止。这种模式的目的…

go语言linux安装

下载&#xff1a;https://go.dev/dl/ 命令行使用 wget https://dl.google.com/go/go1.19.3.linux-amd64.tar.gz解压下载的压缩包&#xff0c;linux建议放在/opt目录下 我放在/home/ihan/go_sdk下 sudo tar -C /home/ihan/go_sdk -xzf go1.19.3.linux-amd64.tar.gz 这里的参数…

STM32作业实现(一)串口通信

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

谷歌发布文生视频模型——Veo,可生成超过一分钟高质量1080p视频

前期我们介绍过OpenAI的文生视频大模型-Sora 模型&#xff0c;其模型一经发布&#xff0c;便得到了大家疯狂的追捧。而Google最近也发布了自己的文生视频大模型Veo&#xff0c;势必要与OpenAI进行一个正面交锋。 Veo 是Google迄今为止最强大的视频生成模型。它可以生成超过一分…

学习小心意——python创建类与对象

在python中&#xff0c;类表示具有相同属性和方法的对象的集合&#xff0c;一般而言都是先定义类再创建类的实例&#xff0c;然后再通过类的实例去访问类的属性和方法 定义类 类中可以定义为数据成员和成员函数。数据成员用于描述对象特征&#xff08;相当于看人的面貌&#…

针对大模型的上下文注入攻击

大型语言模型&#xff08;LLMs&#xff09;的开发和部署取得了显著进展。例如ChatGPT和Llama-2这样的LLMs&#xff0c;利用庞大的数据集和Transformer架构&#xff0c;能够产生连贯性、上下文准确性甚至具有创造性的文本。LLMs最初和本质上是为静态场景设计的&#xff0c;即输入…

【文档智能】符合人类阅读顺序的文档模型-LayoutReader原理及权重开源

引言 阅读顺序检测旨在捕获人类读者能够自然理解的单词序列。现有的OCR引擎通常按照从上到下、从左到右的方式排列识别到的文本行&#xff0c;但这并不适用于某些文档类型&#xff0c;如多栏模板、表格等。LayoutReader模型使用seq2seq模型捕获文本和布局信息&#xff0c;用于…