C++的类Class

news2025/1/30 10:47:15

文章目录

    • 一、C的struct和C++的类的区别
    • 二、关于OOP
    • 三、举例:一个商品类CGoods
    • 四、构造函数和析构函数
      • 1、定义一个顺序栈
      • 2、用构造和析构代替s.init(5);和s.release();
      • 3、在不同内存区域构造对象
      • 4、深拷贝和浅拷贝
      • 5、构造函数和深拷贝的简单应用
      • 6、构造函数的初始化列表
    • 五、类的各种成员变量和成员方法
      • 1、普通成员变量、静态成员变量
      • 2、普通成员方法、静态成员方法、常成员方法
    • 六、指向类成员(成员变量和成员方法)的指针

一、C的struct和C++的类的区别

以下表格由DeepSeek-R1生成:

特性C 的 structC++ 的 structC++ 的 class
默认访问权限无(仅数据)publicprivate
成员函数不支持支持支持
继承/多态不支持支持支持
构造/析构函数不支持支持支持
模板不支持支持支持
设计用途纯数据聚合简单数据+方法封装复杂对象行为

实际开发中,C++ 的 struct 和 class 仅默认权限不同,但习惯上用 struct 表示数据为主的结构,class 表示具有复杂行为的对象。

  • 在C中:
    各种各样的函数的定义、struct
  • 在C++中:
    实体(属性、行为)            ->            ADT(abstract data type)
    对象            <-(实例化)       类(属性->成员变量行为->成员方法)

二、关于OOP

  1. Object Oriented Programming:面向对象程序设计
  2. OOP语言的四大特性:抽象、封装/隐藏、继承、多态
  3. 类中的访问限定符:(由DeepSeek-R1生成)
基类成员访问限定符类内部访问继承方式派生类中基类成员的访问权限外部代码访问友元访问
publicpublic 继承public
protected 继承protected
private 继承private
protectedpublic 继承protected
protected 继承protected
private 继承private
private任何继承方式不可访问

三、举例:一个商品类CGoods

#include <iostream>
using namespace std;

const int NAME_LEN = 20;

class CGoods {
public: // 给外部提供公有的成员方法,来访问私有的属性
	// 商品数据初始化
	void init(const char *name, double price, int amount);
	// 打印商品信息
	void show();
	// 给成员变量提供getXXX或setXXX的方法(注意:类内部实现的方法,自动处理成inline内联函数)
	void setName(const char *name) { strcpy_s(_name, sizeof(_name), name); }
	void setPrice(double price) { _price = price; }
	void setAmount(int amount) { _amount = amount; }
	const char *getName() { return _name; }
	double getPrice() { return _price; }
	int getAmount() { return _amount; }
private:
	char _name[NAME_LEN];
	double _price;
	int _amount;
};

void CGoods::init(const char *name, double price, int amount) {
	strcpy_s(_name, sizeof(_name), name);
	_price = price;
	_amount = amount;
}

void CGoods::show() {
	cout << "name: " << _name << endl;
	cout << "price: " << _price << endl;
	cout << "amount: " << _amount << endl;
}

int main() {
	CGoods good1;
	good1.init("面包", 10.0, 200); 
	good1.show();

	good1.setPrice(20.5); 
	good1.setAmount(100); 
	good1.show();
	
	CGoods good2;
	good2.init("空调", 10000.0, 50);
	good2.show();

	return 0;
}

注意:

  1. 类可以定义无数个对象,每一个对象都有自己的成员变量,但是它们共享一套成员方法。
  2. 类内部实现的方法,自动处理成inline内联函数,外部则不会。
  3. 对象的内存大小,与成员变量有关。VS2022下可以通过cl C++面向对象.cpp /dlreportSingleClassLayoutCGoods查看占用内存大小。
  4. init(name,price,amount)怎么知道处理哪个对象的信息,把信息初始化给哪一个对象的呢?
    类的成员方法一经编译,所有的方法参数,都会加一个this指针,接收调用该方法的对象的地址。
	void init(CGoods *this, const char *name, double price, double amount);

	void CGoods::init(CGoods *this, const char *name, double price, int amount) {
		strcpy_s(this->_name, sizeof(this->_name), name);
		this->_price = price;
		this->_amount = amount;
	}
	
	init(&good1, "面包", 10.0, 200);

四、构造函数和析构函数

1、定义一个顺序栈

#include <iostream>
using namespace std;

const int NAME_LEN = 20;

class SeqStack {
public: 
	void init(int size = 10) {
		_pstack = new int[size];
		_top = -1;
		_size = size;
	}
	void release() {
		delete[]_pstack;
		_pstack = nullptr;
	}
	void push(int val) {
		if (full()) {
			resize();
		}
		_pstack[++_top] = val;
	}
	void pop() {
		if (empty()) {
			return;
		}
		--_top;
	}
	int top() {
		return _pstack[_top];
	}
	bool empty() { return _top == -1; }
	bool full() { return _top == _size - 1; }

private:
	int *_pstack;
	int _top;
	int _size;

	void resize() {
		int* ptmp = new int[_size * 2];
		for (int i = 0; i < _size; ++i) {
			ptmp[i] = _pstack[i];
		} // memcpy(ptmp, _pstack, sizeof(int)*size);或realloc可能产生深拷贝浅拷贝的问题
		delete[]_pstack;
		_pstack = ptmp;
		_size *= 2;
	}
};


int main() {
	SeqStack s;
	s.init(5); 

	for (int i = 0; i < 15; ++i) {
		s.push(rand() % 100);

	}

	while (!s.empty()) {
		cout << s.top() << " ";
		s.pop();
	}

	s.release();

	return 0;
}

2、用构造和析构代替s.init(5);和s.release();

#include <iostream>
using namespace std;

const int NAME_LEN = 20;

class SeqStack {
public: 
	SeqStack(int size = 10) { // 构造函数可带参数,可以重载
		_pstack = new int[size];
		_top = -1;
		_size = size;
	}
	~SeqStack() { // 不带参数,只能有一个
		delete[]_pstack;
		_pstack = nullptr;
	}
	void push(int val) {
		if (full()) {
			resize();
		}
		_pstack[++_top] = val;
	}
	void pop() {
		if (empty()) {
			return;
		}
		--_top;
	}
	int top() {
		return _pstack[_top];
	}
	bool empty() { return _top == -1; }
	bool full() { return _top == _size - 1; }

private:
	int *_pstack;
	int _top;
	int _size;

	void resize() {
		int* ptmp = new int[_size * 2];
		for (int i = 0; i < _size; ++i) {
			ptmp[i] = _pstack[i];
		} // memcpy(ptmp, _pstack, sizeof(int)*size);或realloc可能产生深拷贝浅拷贝的问题
		delete[]_pstack;
		_pstack = ptmp;
		_size *= 2;
	}
};


int main() {
	//1.开辟内存 2.调用构造函数
	SeqStack s(5);
	//s.init(5); // 对象成员变量的初始化

	for (int i = 0; i < 15; ++i) {
		s.push(rand() % 100);

	}

	while (!s.empty()) {
		cout << s.top() << " ";
		s.pop();
	}

	//s.release(); // 释放对象成员变量占用的外部堆内存(外部资源)
	return 0;
}

3、在不同内存区域构造对象

#include <iostream>
using namespace std;

const int NAME_LEN = 20;

class SeqStack {
public: 
	SeqStack(int size = 10) {
		cout << this << " SeqStack" << endl;
		_pstack = new int[size];
		_top = -1;
		_size = size;
	}
	~SeqStack() {
		cout << this << " ~SeqStack" << endl;
		delete[]_pstack;
		_pstack = nullptr;
	}
	void push(int val) {
		if (full()) {
			resize();
		}
		_pstack[++_top] = val;
	}
	void pop() {
		if (empty()) {
			return;
		}
		--_top;
	}
	int top() {
		return _pstack[_top];
	}
	bool empty() { return _top == -1; }
	bool full() { return _top == _size - 1; }

private:
	int *_pstack;
	int _top;
	int _size;

	void resize() {
		int* ptmp = new int[_size * 2];
		for (int i = 0; i < _size; ++i) {
			ptmp[i] = _pstack[i];
		} // memcpy(ptmp, _pstack, sizeof(int)*size);或realloc可能产生深拷贝浅拷贝的问题
		delete[]_pstack;
		_pstack = ptmp;
		_size *= 2;
	}
};

/*
.data
heap
stack
*/
SeqStack s0; //.data

int main() {
	cout << "heap上对象构造" << endl;
	SeqStack* ps = new SeqStack(60); // heap malloc内存开辟+SeqStack对象构造
	ps->push(70);
	ps->push(80);
	ps->pop();
	cout << ps->top() << endl;
	delete ps; // 先调用ps->~SeqStack()+然后free(ps)

	cout << "stack上对象构造" << endl;
	SeqStack s(5); //stack

	for (int i = 0; i < 15; ++i) {
		s.push(rand() % 100);
	}

	while (!s.empty()) {
		cout << s.top() << " ";
		s.pop();
	}
	cout << endl;

	return 0;
}

打印结果如下:

00007FF7FB3914C0 SeqStack
heap上对象构造
0000026D43E94EF0 SeqStack
70
0000026D43E94EF0 ~SeqStack
stack上对象构造
000000F8EF6FF9D8 SeqStack
61 27 81 45 5 64 62 58 78 24 69 0 34 67 41
000000F8EF6FF9D8 ~SeqStack
00007FF7FB3914C0 ~SeqStack

4、深拷贝和浅拷贝

	SeqStack s; // 没有提供任何构造函数的时候,会为你生成默认构造函数
	SeqStack s1(10);
	SeqStack s2 = s1; // #1 默认拷贝构造函数 -》做直接内存数据拷贝
	//Seqstack s3(s1);// #2 同1

在这里插入图片描述
上述默认构造函数导致出现浅拷贝的问题,浅拷贝一般包括以下几种问题:

  1. 多个对象共享同一资源:
    如果多个对象的指针成员指向同一块内存,修改其中一个对象会影响其他对象。

  2. 重复释放资源:
    当多个对象的指针指向同一块内存时,析构函数可能会多次释放同一块内存,导致程序崩溃。

  3. 内存泄漏:
    如果资源被浅拷贝后,原始对象的资源没有被正确释放,会导致内存泄漏。

默认拷贝构造函数:浅拷贝

	SeqStack(const SeqStack &src) {
		_pstack = src._pstack;
		_top = src._top;
		_size = src._size;
	}

深拷贝

	SeqStack(const SeqStack &src) {
		_pstack = new int[src._size];
		for (int i = 0; i <= src._top; ++i) {
			_pstack[i] = src._pstack[i];
		}
		_top = src._top;
		_size = src._size;
	}

如果对两个已经存在的对象进行赋值操作,也会出现浅拷贝问题

int main() {
	cout << "开始构造s" << endl;
	SeqStack s; // 没有提供任何构造函数的时候,会为你生成默认构造函数
	cout << "开始构造s1" << endl;
	SeqStack s1(10);
	cout << "开始构造s2" << endl;
	SeqStack s2 = s1; // #1 默认拷贝构造函数 -》做直接内存数据拷贝
	//Seqstack s3(s1);// #2 同1

	s2 = s1;

	return 0;
}

s2 = s1; // 默认的赋值函数 =》做直接的内存拷贝
修改如下:
// s2.operator=(s1)
// void operator=(const SeqStack &src)

#include <iostream>
using namespace std;

const int NAME_LEN = 20;

class SeqStack {
public: 
	SeqStack(int size = 10) {
		cout << this << " SeqStack" << endl;
		_pstack = new int[size];
		_top = -1;
		_size = size;
	}
	// 自定义拷贝构造函数
	SeqStack(const SeqStack& src) { 
		cout << this << " const SeqStack& src" << endl;
		_pstack = new int[src._size];
		for (int i = 0; i <= src._top; ++i) {
			_pstack[i] = src._pstack[i];
		}
		_top = src._top;
		_size = src._size;
	}
	// 赋值重载函数
	void operator=(const SeqStack& src) {
		cout << this << " operator=" << endl;
		// 防止自赋值
		if (this == &src) {
			return;
		}
		// 需要先释放当前对象占用的外部资源
		delete[]_pstack;

		_pstack = new int[src._size];
		for (int i = 0; i <= src._top; ++i) {
			_pstack[i] = src._pstack[i];
		}
		_top = src._top;
		_size = src._size;
	}

	~SeqStack() {
		cout << this << " ~SeqStack" << endl;
		delete[]_pstack;
		_pstack = nullptr;
	}
	void push(int val) {
		if (full()) {
			resize();
		}
		_pstack[++_top] = val;
	}
	void pop() {
		if (empty()) {
			return;
		}
		--_top;
	}
	int top() {
		return _pstack[_top];
	}
	bool empty() { return _top == -1; }
	bool full() { return _top == _size - 1; }

private:
	int *_pstack;
	int _top;
	int _size;

	void resize() {
		int* ptmp = new int[_size * 2];
		for (int i = 0; i < _size; ++i) {
			ptmp[i] = _pstack[i];
		} // memcpy(ptmp, _pstack, sizeof(int)*size);或realloc可能产生深拷贝浅拷贝的问题
		delete[]_pstack;
		_pstack = ptmp;
		_size *= 2;
	}
};

int main() {
	cout << "开始构造s" << endl;
	SeqStack s; // 没有提供任何构造函数的时候,会为你生成默认构造函数
	cout << "开始构造s1" << endl;
	SeqStack s1(10);
	cout << "开始构造s2" << endl;
	SeqStack s2 = s1; // #1 默认拷贝构造函数 -》做直接内存数据拷贝
	//Seqstack s3(s1);// #2 同1

	s2 = s1;

	return 0;
}

打印结果:

开始构造s
0000003B8E14F6C8 SeqStack
开始构造s1
0000003B8E14F6F8 SeqStack
开始构造s2
0000003B8E14F728 const SeqStack& src
0000003B8E14F728 operator=
0000003B8E14F728 ~SeqStack
0000003B8E14F6F8 ~SeqStack
0000003B8E14F6C8 ~SeqStack

5、构造函数和深拷贝的简单应用

  1. 字符串String
#include <iostream>
using namespace std;


class String {
public: 
	String(const char* str = nullptr) { // 普通构造函数
		if (str != nullptr) {
			m_data = new char[strlen(str) + 1];
			strcpy_s(m_data, strlen(str) + 1, str);
		}
		else {
			m_data = new char[1];
			*m_data = '\0';
		}
	}

	String(const String& other) { // 拷贝构造函数
		m_data = new char[strlen(other.m_data) + 1];
		strcpy_s(m_data, strlen(other.m_data) + 1, other.m_data);
	}

	~String() {
		delete[]m_data;
		m_data = nullptr;
	}

	String& operator=(const String& other) { // 返回值不是void,而是当前类型的引用,是为了连续赋值
		if (this == &other) {
			return *this;
		}

		delete[]m_data;

		m_data = new char[strlen(other.m_data) + 1];
		strcpy_s(m_data, strlen(other.m_data) + 1, other.m_data);
		return *this;
	}

private:
	char* m_data;
};

int main() {
	// 调用带const char*参数的构造函数
	String str1;
	String str2("hello");
	String str3 = "world";

	// 调用拷贝构造函数
	String str4 = str3;
	String str5(str4);

	// 调用赋值重载函数
	str1 = str2;
	str3 = str1 = str2; // 连续赋值

	return 0;
}

  1. 循环队列Queue
#include <iostream>
using namespace std;

class Queue {
public: 
	Queue(int size = 20) {
		_pQue = new int[size];
		_front = _rear = 0;
		_size = size;
	}

	Queue(const Queue &src) {
		_front = src._front;
		_rear = src._rear;
		_size = src._size;

		_pQue = new int[_size];
		for (int i = _front; i != _rear; i = (i + 1) % _size) {
			_pQue[i] = src._pQue[i];
		}
	}

	Queue& operator=(const Queue& src) {
		if (this == &src) {
			return *this;
		}

		delete[]_pQue;

		_front = src._front;
		_rear = src._rear;
		_size = src._size;

		_pQue = new int[_size];
		for (int i = _front; i != _rear; i = (i + 1) % _size) {
			_pQue[i] = src._pQue[i];
		}
		return *this;

	}

	~Queue() {
		delete[]_pQue;
		_pQue = nullptr;
	}

	void push(int val) {// 入队操作
		if (full()) {
			resize();
		}
		_pQue[_rear] = val;
		_rear = (_rear + 1) % _size;
	}

	void pop() { // 出队操作
		if (empty()) {
			return;
		}
		_front = (_front + 1) % _size;
	}

	int front() {
		return _pQue[_front];
	}

	bool full() {
		return (_rear + 1) % _size == _front;
	}

	bool empty() {
		return _front == _rear;
	}

private:
	int* _pQue; // 申请队列的数组空间
	int _front; // 指示队头的位置
	int _rear; // 指示队尾的位置
	int _size; // 队列扩容的总大小

	void resize() {
		int* ptmp = new int[2 * _size];
		int index = 0;
		for (int i = _front; i != _rear; i = (i + 1) % _size) {
			ptmp[index++] = _pQue[i];
		}
		delete[]_pQue;
		_pQue = ptmp;
		_front = 0;
		_rear = index;
		_size *= 2;
	}
};

int main() {
	Queue q;
	for (int i = 0; i < 20; ++i) {
		q.push(rand() % 100);
	}

	while (!q.empty()) {
		cout << q.front() << " ";
		q.pop();
	}
	cout << endl;

	Queue q1 = q;
	q1 = q;

	return 0;
}

6、构造函数的初始化列表

#include <iostream>
using namespace std;

class CDate {
public:
	CDate(int y, int m, int d) { //自定义的构造函数
		_year = y;
		_month = m;
		_day = d;
	}

	void show() {
		cout << _year << "/" << _month << "/" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day; 

};

/*
构造函数的初始化列表: 可以指定当前对象成员变量的初始化方式
CDate信息  CGoods商品信息的一部分  a part of ...  组合的关系
*/
class CGoods {
public: 
	// "CDate"没有合适的构造函数可用,因此在这里使用初始化列表
	CGoods(const char *n, int a, double p, int y, int m, int d)
		: _date(y, m, d)
		, _amount(a) // 相当于int _amount = a;直接进行初始化,
					 // 避免了先定义(int _amount; _amount = a;)需要调用默认构造函数,
					 // 而CDate因为定义了自定义的构造函数,不会调用默认构造函数
		, _price(p)  // #1 构造函数的初始化列表
	{
		// #2 当前类类型构造函数体
		strcpy_s(_name, 20, n);
	}

	void show() {
		cout << "name: " << _name << endl;
		cout << "amount: " << _amount << endl;
		cout << "price: " << _price << endl;
		_date.show();
	}

private:
	char _name[20];
	int _amount;
	double _price;
	CDate _date;    // 成员对象 1.分配内存 2.调用构造函数 
};

int main() {
	CGoods good("商品", 100, 35.0, 2025, 1, 27);
	good.show();

	return 0;
}

注意:成员变量的初始化和它们定义的顺序有关,和构造函数初始化列表中出现的先后顺序无关!

#include <iostream>
using namespace std;

class Test {
public: 
	Test(int m = 10):mb(m), ma(mb) {}
	void show() {
		cout << "ma: " << ma << "mb: " << mb << endl;
	}

private:
	int ma;
	int mb;
};

int main() {
	Test t; 
	t.show(); // ma: -858993460 mb: 10

	return 0;
}

Windows下会将未初始化的内存填充为特定的值0xCCCCCCCC(十进制为-858993460),先初始化ma,而此时mb未初始化,其值-858993460,因此ma: -858993460,而mb: 10。

五、类的各种成员变量和成员方法

1、普通成员变量、静态成员变量

2、普通成员方法、静态成员方法、常成员方法

  • 普通的成员方法 =>编译器会添加一个this形参变量
    1.属于类的作用域
    2.调用该方法时,需要依赖一个对象!常对象是无法调用的 实参:const CGoods* -》CGoods *this
    3.可以任意访问对象的私有成员 protected继承 public private
  • static静态成员方法 =>不会生成this形参
    1.属于类的作用域
    2.用类名作用域来调用方法
    3.可以任意访问对象的私有成员,仅限于不依赖对象的成员(只能调用其它的static静态成员)
  • const常成员方法 const CGoods *this
    1.属于类的作用域
    2.调用依赖一个对象,普通对象或者常对象都可以
    3.可以任意访问对象的私有成员,但是只能读,而不能写(只要是只读操作的成员方法,一律实现成const常成员方法)
#include <iostream>
using namespace std;

const int NAME_LEN = 20;

class CGoods {
public:
	CGoods(const char* name, double price, int amount);
	void show();
	void show() const;
	static void showCount();

private:
	char _name[NAME_LEN];
	double _price;
	int _amount;
	static int _count; // 声明 用来记录商品对象的总数量;不属于对象,而属于类级别的
};

// static成员变量一定要在类外进行定义并且初始化
int CGoods::_count = 0; 

CGoods::CGoods(const char* name, double price, int amount) {
	strcpy_s(_name, sizeof(_name), name);
	_price = price;
	_amount = amount;

	_count++; // 记录所有产生的新对象的数量
}

// 普通成员方法 CGoods *this
void CGoods::show() {
	cout << "name: " << _name << endl;
	cout << "price: " << _price << endl;
	cout << "amount: " << _amount << endl;
}

// 常成员方法 const CGoods *this
void CGoods::show() const {
	cout << "name: " << _name << endl;
	cout << "price: " << _price << endl;
	cout << "amount: " << _amount << endl;
}

// 静态成员方法 没有this指针
void CGoods::showCount() {
	cout << "所有商品数量: " << _count << endl;
}

int main() {
	CGoods good1("面包", 10.0, 200);
	good1.show();

	CGoods good2("空调", 100.0, 50);
	good2.show();

	CGoods::showCount();

	const CGoods good3("非卖品", 10000.0, 1);
	good3.show(); //CGoods::show(&good3) const CGoods* -> CGoods*不可以

	return 0;
}

六、指向类成员(成员变量和成员方法)的指针

指向普通成员变量的指针依赖于对象的调用,指向静态成员变量的指针不依赖。
指向普通成员方法的函数指针同样依赖于对象的调用,指向静态成员方法的指针不依赖。

#include <iostream>
using namespace std;

class Test {
public:
	void func() { cout << "call Test::func" << endl; }
	static void static_func() { cout << "Test::static func" << endl; }

	int ma;
	static int mb;
};

int Test::mb;

int main() {
	Test t1; 
	Test *t2 = new Test();

	// 指向成员变量的指针
	// int a=10; int *p=&a; *p=30;
	int Test::*p = &Test::ma;
	t1.*p = 20;
	cout << t1.*p<< endl;
	t2->*p = 30; 
	cout << t2->*p << endl; 

	// 指向静态成员变量的指针
	int *p1 = &Test::mb;
	*p1 = 40;
	cout << *p1 << endl;

	// 指向成员方法的指针
	void (Test::*pfunc)() = &Test::func; 
	(t1.*pfunc)();
	(t2->*pfunc)();

	// 定义函数指针指向类的静态成员方法
	void(*pfunc1)() = &Test::static_func;
	(*pfunc1)();

	delete t2;
	return 0;
}

打印结果如下:

20
30
40
call Test::func
call Test::func
Test::static func

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

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

相关文章

接口 V2 完善:分布式环境下的 WebSocket 实现与 Token 校验

&#x1f3af; 本文档详细介绍了如何使用WebSocket协议优化客户端与服务端之间的通信&#xff0c;特别是在处理异步订单创建通知的场景中。通过引入WebSocket代替传统的HTTP请求-响应模式&#xff0c;实现了服务器主动向客户端推送数据的功能&#xff0c;极大地提高了实时性和效…

2025年数学建模美赛:A题分析(1)Testing Time: The Constant Wear On Stairs

2025年数学建模美赛 A题分析&#xff08;1&#xff09;Testing Time: The Constant Wear On Stairs 2025年数学建模美赛 A题分析&#xff08;2&#xff09;楼梯磨损分析模型 2025年数学建模美赛 A题分析&#xff08;3&#xff09;楼梯使用方向偏好模型 2025年数学建模美赛 A题分…

使用Vue3实现可拖拽的九点导航面板

开篇 本文使用Vue3实现了一个可拖拽的九宫导航面板。这个面板在我这里的应用场景是我个人网站的首页的位置&#xff0c;九宫导航对应的是用户最后使用或者最多使用的九个功能&#xff0c;正常应该是由后端接口返回的&#xff0c;不过这里为了简化&#xff0c;写的是固定的数组数…

68-《贝壳花》

贝壳花 贝壳花&#xff08;学名&#xff1a;Moluccella laevis Linn.&#xff09;是属于唇形科&#xff0c;贝壳花是一、二年的草本。植株高5至60cm&#xff0c;茎四棱&#xff0c;不分枝。叶对生&#xff0c;心脏状圆形&#xff0c;边缘疏生齿牙&#xff1b;叶柄和叶近等长。花…

【自然语言处理(NLP)】深度循环神经网络(Deep Recurrent Neural Network,DRNN)原理和实现

文章目录 介绍深度循环神经网络&#xff08;DRNN&#xff09;原理和实现结构特点工作原理符号含义公式含义 应用领域优势与挑战DRNN 代码实现 个人主页&#xff1a;道友老李 欢迎加入社区&#xff1a;道友老李的学习社区 介绍 **自然语言处理&#xff08;Natural Language Pr…

2025数学建模美赛|F题成品论文

国家安全政策与网络安全 摘要 随着互联网技术的迅猛发展&#xff0c;网络犯罪问题已成为全球网络安全中的重要研究课题&#xff0c;且网络犯罪的形式和影响日益复杂和严重。本文针对网络犯罪中的问题&#xff0c;基于多元回归分析和差异中的差异&#xff08;DiD&#xff09;思…

自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测

代码&#xff1a; import torch import numpy as np import torch.nn as nn# 定义数据&#xff1a;x_data 是特征&#xff0c;y_data 是标签&#xff08;目标值&#xff09; data [[-0.5, 7.7],[1.8, 98.5],[0.9, 57.8],[0.4, 39.2],[-1.4, -15.7],[-1.4, -37.3],[-1.8, -49.…

关于使用PHP时WordPress排错——“这意味着您在wp-config.php文件中指定的用户名和密码信息不正确”的解决办法

本来是看到一位好友的自己建站&#xff0c;所以突发奇想&#xff0c;在本地装个WordPress玩玩吧&#xff0c;就尝试着装了一下&#xff0c;因为之前电脑上就有MySQL&#xff0c;所以在自己使用PHP建立MySQL时报错了。 最开始是我的php启动mysql时有问题&#xff0c;也就是启动过…

【蓝桥杯】43694.正则问题

题目描述 考虑一种简单的正则表达式&#xff1a; 只由 x ( ) | 组成的正则表达式。 小明想求出这个正则表达式能接受的最长字符串的长度。 例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是&#xff1a; xxxxxx&#xff0c;长度是 6。 输入描述 一个由 x()| 组成的正则表达式。…

服务器虚拟化技术详解与实战:架构、部署与优化

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在现代 IT 基础架构中&#xff0c;服务器虚拟化已成为提高资源利用率、降低运维成本、提升系统灵活性的重要手段。通过服务…

jvm--类的生命周期

学习类的生命周期之前&#xff0c;需要了解一下jvm的几个重要的内存区域&#xff1a; &#xff08;1&#xff09;方法区&#xff1a;存放已经加载的类信息、常量、静态变量以及方法代码的内存区域 &#xff08;2&#xff09;常量池&#xff1a;常量池是方法区的一部分&#x…

TensorFlow实现逻辑回归模型

逻辑回归是一种经典的分类算法&#xff0c;广泛应用于二分类问题。本文将介绍如何使用TensorFlow框架实现逻辑回归模型&#xff0c;并通过动态绘制决策边界和损失曲线来直观地观察模型的训练过程。 数据准备 首先&#xff0c;我们准备两类数据点&#xff0c;分别表示两个不同…

《十七》浏览器基础

浏览器&#xff1a;是安装在电脑里面的一个软件&#xff0c;能够将页面内容渲染出来呈现给用户查看&#xff0c;并让用户与网页进行交互。 常见的主流浏览器&#xff1a; 常见的主流浏览器有&#xff1a;Chrome、Safari、Firefox、Opera、Edge 等。 输入 URL&#xff0c;浏览…

网络安全 | F5-Attack Signatures-Set详解

关注&#xff1a;CodingTechWork 创建和分配攻击签名集 可以通过两种方式创建攻击签名集&#xff1a;使用过滤器或手动选择要包含的签名。  基于过滤器的签名集仅基于在签名过滤器中定义的标准。基于过滤器的签名集的优点在于&#xff0c;可以专注于定义用户感兴趣的攻击签名…

STranslate 中文绿色版即时翻译/ OCR 工具 v1.3.1.120

STranslate 是一款功能强大且用户友好的翻译工具&#xff0c;它支持多种语言的即时翻译&#xff0c;提供丰富的翻译功能和便捷的使用体验。STranslate 特别适合需要频繁进行多语言交流的个人用户、商务人士和翻译工作者。 软件功能 1. 即时翻译&#xff1a; 文本翻译&#xff…

基于微信小程序的助农扶贫系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

我谈区域偏心率

偏心率的数学定义 禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》P312 区域的拟合椭圆看这里。 Rafael Gonzalez的二阶中心矩的表达不说人话。 我认为半长轴和半短轴不等于特征值&#xff0c;而是特征值的根号。…

关于低代码技术架构的思考

我们经常会看到很多低代码系统的技术架构图&#xff0c;而且经常看不懂。是因为技术架构图没有画好&#xff0c;还是因为技术不够先进&#xff0c;有时候往往都不是。 比如下图&#xff1a; 一个开发者&#xff0c;看到的视角往往都是技术层面&#xff0c;你给用户讲React18、M…

若依路由配置教程

1. 路由配置文件 2. 配置内容介绍 { path: "/tool/gen-edit", component: Layout, //在路由下&#xff0c;引用组件的名称&#xff0c;在页面中包括这个组件的内容(页面框架内容) hidden: true, //此页面的内容&#xff0c;在左边的菜单中不用显示。 …