C++必修:类与对象(三)

news2024/11/20 20:36:36

✨✨ 欢迎大家来到贝蒂大讲堂✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C++学习
贝蒂的主页:Betty’s blog

1. 隐式类型转换

在学习C语言时我们就明白,当我们进行赋值时,如果赋值两边的类型不同时就可能发生隐式类型转换

1.1. 内置类型

在发生隐式类型转换时,如果都是内置类型就会先开辟一个临时变量,再将右操作数强制类型转换为左操作数的类型,最后用这个临时变量对左操作数进行赋值。注意:这个临时变量具有常性,不可修改。

img

int main()
{
	double j = 1.1;
	int i = j;//隐式类型转换
	int& a = j;//error
	const int& b = j;//ok
	return 0;
}

因为临时变量具有常性,所以无法被修改。如果赋值给普通引用就会造成权限的放大,所以只能用常引用。

1.2. 自定义类型

如果将一个内置赋值给自定义类型,那么编译器也会先创造一个自定义类型的**临时变量,**然后用这个内置类型调用构造函数对临时变量初始化,最后用这个临时变量对左操作数进行拷贝构造。。注意:这个临时变量也具有常性,不可修改。

img

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1 = 2023;//发生隐式类型转换
	Date d2 = { 2023,2 };
	d1.Print();
	d2.Print();
	return 0;
}

1.3. explicit关键字

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

class Date
{
public:
	explicit Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1 = 2023;//发生隐式类型转换
	Date d2 = { 2023,2 };
	d1.Print();
	d2.Print();
	return 0;
}

img

2. 类的静态成员

2.1. 定义

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数

class A
{
public:
    static int Print()//静态成员函数
	{
		cout << "Print()" << endl;
	}
private:
	static int _a;//静态成员变量
};

2.2. 注意

  1. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。
  2. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。所以可以通过类名::静态成员或者 对象.静态成员来访问。
class A
{
public:
	static void Print()//静态成员函数
	{
		cout << "Print()" << endl;
	}
private:
	static int _a;//静态成员变量
};
int main()
{
	A a;
	a.Print();
	A::Print();
	return 0;
}

img

  1. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
int A::_a = 1;//类外定义
  1. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。比如说:静态函数就无法访问非静态函数。
	static void Print()//静态成员函数
	{
		cout << "Print()" << endl;
		Add(1, 2);//无法访问非静态成员
	}
	int Add(int x, int y)
	{
		return x + y;
	}

但是非静态成员函数能访问静态成员函数。

	static void Print()//静态成员函数
	{
		cout << "Print()" << endl;
	}
	int Add(int x, int y)
	{
		return x + y;
		Print();
	}

3. 友元

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

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

3.1. 友元函数

有时在类外我们需要访问类中的数据,但由于访问限定符的限制并不能访问私有成员。这时如果一定要访问的话就需要借助我们的友元函数,它的用法十分简单,只用在类中加入friend+该函数的声明

class Date
{
	friend void Print(const Date& d);//友元函数
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
void Print(const Date&d)
{
	cout << d._year << "-" << d._month << "-" << d._day << endl;
}

当然我们也能通过在类中声明获取私有元素的返回函数实现:

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	int GetYear()const
	{
		return _year;
	}
	int GetMonth()const
	{
		return _month;
	}
	int GetDay()const
	{
		return _day;
	}
private:
	int _year;
	int _month;
	int _day;
};
void Print(const Date& d)
{
	cout << d.GetYear() << "-" << d.GetMonth() << "-" << d.GetDay() << endl;
}

注意:

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

3.2. 友元类

除了友元函数外,还有一种友元类。友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。与友元函数用法类似:在一个类中声明friend+class+类名

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 = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

注意:

  1. **友元关系是单向的,不具有交换性。**比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
  2. **友元关系不能传递。**如果C是B的友元, B是A的友元,则不能说明C时A的友元。
  3. 友元关系不能继承。在继承位置再给大家详细介绍。

4. 内部类

4.1. 定义

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

class A
{
public:
	class B//B是A的友元
	{
	private:
		int _m;
	};
private:
	int _a;
	int _b;
};

4.2. 注意

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象 / 类名。
class A
{
private:
	static int k;
	int h;
public:
	class B // B天生就是A的友元
	{
	public:
		void foo()
		{
			cout << k << endl;//OK
		}
	};
};
int A::k = 1;
int main()
{
	A::B b;
	b.foo();
	return 0;
}

img

  1. 外部类的大小与内部类的大小没有关系,sizeof(外部类) = 外部类。
class A
{
private:
	int k;
	int h;
public:
	class B // B天生就是A的友元
	{
	public:
		int _a;
	};
};
int main()
{
	A a;
	cout << sizeof(a) << endl;
	return 0;
}

img

5. 匿名对象

匿名对象与C语言中的匿名结构体类似,只有类名,作用域只在匿名对象声明的一行。

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		cout << "Date" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		cout << "Date(const Date& d)" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "~Date()" << endl;
		_year = _month = _day = 0;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date();//匿名对象
	Date d;
	return 0;
}

img

但是我们也能通过引用延长匿名对象的生命周期。

int main()
{
	const Date& dc = Date();//匿名对象也具有常性
	Date d;
	return 0;
}

img

6. 编译器的一些优化

下面我们将介绍一些编译器对自定义类型常见的优化,我们还是以日期类举例:

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		cout << "Date" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		cout << "Date(const Date& d)" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "~Date()" << endl;
		_year = _month = _day = 0;
	}
private:
	int _year;
	int _month;
	int _day;
};
  • 直接构造+拷贝构造=>直接构造

img

  • 直接构造+拷贝构造+拷贝构造=>直接构造

img

  • 直接构造+直接构造+拷贝构造+赋值重载=>直接构造+直接构造

img

7. 日期类的模拟实现

下面让我们来实现一个功能比较丰富的日期类。

7.1. 项目功能

  1. 日期之间的比较(>,<,>=,<=,==,!=)。
  2. 日期的递增与递减。
  3. 日期+天数(+,+=)。
  4. 日期-天数(-,-=)。
  5. 日期-日期。
  6. 流输入与流输出。
  7. 打印日期。

7.2. 功能实现

7.2.1. 构造与析构函数

在写构造函数之前我们需要写一个函数判断当前日期是否合法。

int Date:: GetMonDay(int year, int month)//或许当月天数
{
	int months[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int day = months[month];
	if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		day++;
	}
	return day;
}

构造函数与拷贝构造与赋值重载。注意:缺省参数在定义时不需要书写

Date::Date(int year, int month, int day)//构造
{
	assert(month > 0 && month < 13);
	int days = GetMonDay(year, month);
	if (day >= 0 && day <= days)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		cout << "输入日期不合法" << endl;
	}
}
Date::Date(const Date& d)//拷贝构造
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}
Date& Date::operator=(const Date& d)//赋值重载
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}

析构函数:

Date::~Date()
{
	_year = _month = _day = 0;
}
7.2.2. 两个日期之间的比较
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);
}
bool Date::operator>(const Date& d) const//大于
{
	if (_year > d._year) 
	{
		return true;
	}
	else if (_year == d._year && _month > d._month) 
	{
		return true;
	}
	else if (_year == d._year && _month == d._month && _day > d._day) 
	{
		return true;
	}
	else 
	{
		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);
}
7.2.3. 自增与自减

为了区分前置与后置的区别,C++规定在重载时前置并不需要额外的参数,后置需要一个额外的int参数。

Date& Date::operator++()//前置++
{
	*this += 1;
	return *this;
}
Date Date::operator++(int)//后置++
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}
Date& Date::operator--()//前置--
{
	*this -= 1;
	return *this;
}
Date Date::operator--(int)//后置--
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}
7.2.4. 日期与天数直接的计算
Date& Date::operator+=(int day)//+=
{
	if (day < 0)
	{
		*this -= -day;
		return *this;
	}
	_day += day;
	while (_day > GetMonDay(_year, _month))
	{
		_day -= GetMonDay(_year, _month);
		++_month;
		if (_month > 12)
		{
			_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;
	}
	while (day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonDay(_year, _month);
	}
	return *this;
}
Date Date::operator-(int day)const//-
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}
int Date::operator-(const Date& d)const//相差
{
	Date max = *this;
	Date min = d;
	int flag = 1;
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}//求最大
	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}

	return flag * n;
}
7.2.5. 打印
void Date::Print()const//打印
{
	cout<< _year << "/" << _month << "/" << _day;
}
7.2.6. 流插入与流提取

因为重载后的运算符顺序与参数顺序相同,为了符合习惯,我们只好在类外定义。并且因为函数较短,可以声明为了内联函数。

inline ostream& operator<<(ostream& out, const Date& d)//流输出
{
	out << d._year << "/" << d._month << "/" << d._day <<endl;
	return out;
}

inline istream& operator>>(istream& in, Date& d)//流输入
{
	in >> d._year >> d._month >> d._day;
	return in;
}

7.3. 完整代码

7.3.1. Date.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
	friend inline ostream& operator<<(ostream& out, const Date& d);
	friend inline istream& operator>>(istream& in, Date& d);
public:
	int GetMonDay(int year, int month);//或许当月天数
	Date(int year = 1, int month = 1, int day = 1);//构造
	Date(const Date& d);//拷贝构造
	Date& operator=(const Date& d);//赋值重载
	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;//小于等于
	Date& operator+=(int day);//+=
	Date operator+(int day)const;//+
	Date& operator-=(int day);//-=
	Date operator-(int day)const;//-
	Date& operator++();//前置++
	Date operator++(int);//后置++
	Date& operator--();//前置--
	Date operator--(int);//后置--
	int operator-(const Date& d)const;//相差
	void Print()const;//打印
	~Date();
private:
	int _year;
	int _month;
	int _day;
};
inline ostream& operator<<(ostream& out, const Date& d)//流输出
{
	out << d._year << "/" << d._month << "/" << d._day <<endl;
	return out;
}

inline istream& operator>>(istream& in, Date& d)//流输入
{
	in >> d._year >> d._month >> d._day;
	return in;
}
7.3.2. Date.cpp
#include"Date.h"
int Date:: GetMonDay(int year, int month)//或许当月天数
{
	int months[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int day = months[month];
	if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		day++;
	}
	return day;
}
Date::Date(int year, int month, int day)//构造
{
	assert(month > 0 && month < 13);
	int days = GetMonDay(year, month);
	if (day >= 0 && day <= days)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		cout << "输入日期不合法" << endl;
	}
}
Date::Date(const Date& d)//拷贝构造
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}
Date& Date::operator=(const Date& d)//赋值重载
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}
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);
}
bool Date::operator>(const Date& d) const//大于
{
	if (_year > d._year) 
	{
		return true;
	}
	else if (_year == d._year && _month > d._month) 
	{
		return true;
	}
	else if (_year == d._year && _month == d._month && _day > d._day) 
	{
		return true;
	}
	else 
	{
		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);
}
Date& Date::operator+=(int day)//+=
{
	if (day < 0)
	{
		*this -= -day;
		return *this;
	}
	_day += day;
	while (_day > GetMonDay(_year, _month))
	{
		_day -= GetMonDay(_year, _month);
		++_month;
		if (_month > 12)
		{
			_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;
	}
	while (day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}
		_day += GetMonDay(_year, _month);
	}
	return *this;
}
Date Date::operator-(int day)const//-
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}
Date& Date::operator++()//前置++
{
	*this += 1;
	return *this;
}
Date Date::operator++(int)//后置++
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}
Date& Date::operator--()//前置--
{
	*this -= 1;
	return *this;
}
Date Date::operator--(int)//后置--
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}
int Date::operator-(const Date& d)const//相差
{
	Date max = *this;
	Date min = d;
	int flag = 1;
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}//求最大
	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}

	return flag * n;
}
void Date::Print()const//打印
{
	cout<< _year << "/" << _month << "/" << _day;
}
Date::~Date()
{
	_year = _month = _day = 0;
}

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

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

相关文章

智慧旅游引领旅游行业创新发展:借助智能科技的力量,实现旅游资源的优化配置和高效利用,推动旅游行业的转型升级和可持续发展

目录 一、引言 二、智慧旅游的定义与特点 1、信息化程度高 2、智能化服务丰富 3、互动性强 4、个性化服务突出 5、可持续性发展 三、智慧旅游在旅游行业创新发展中的作用 &#xff08;一&#xff09;优化旅游资源配置 &#xff08;二&#xff09;提升旅游服务质量 &…

vue3 jspdf,element table 导出excel、pdf,横板竖版分页

多个表格需要&#xff0c;pdf需要的格式与原本展示的表格样式不同 1.创建一个新的表格&#xff0c;设置pdf需要的样式&#xff0c;用vue的h函数放入dom中 2.excel用xlxs插件直接传入新建el-table的dom,直接导出 3.pdf导出类似excel黑色边框白底黑字的文件&#xff0c;把el-t…

开源版本管理系统的搭建一:SVN服务端安装

作者&#xff1a;私语茶馆 1.Windows搭建SVN版本管理系统 点评&#xff1a;SVN本身非常简洁易用&#xff0c;VisualSVN文档支撑非常好&#xff0c;客户端TortoiseSVN非常专业。5星好评。 1.1.SVN概要和组成 背景介绍 Svn是一个开源版本管理系统&#xff0c;由CollabNet公司…

ffmpeg 推流

参考 【windows&&linux环境下实现ffmpeg&&vlc rtsp本地视频、摄像头推流&#xff0c;VLC推拉流】 本地视频 推流 localhost 下载 mediamtx 服务器 https://github.com/bluenviron/mediamtx/releases 下载 ffmpeg https://github.com/BtbN/FFmpeg-Builds/rel…

基于vmware虚拟机中yum源的配置

1.首先需确保虚拟机中已经连接了光盘映像&#xff08;如图在虚拟机右下方从左往右第二个&#xff09; 2.在虚拟机中找到光盘映像文件&#xff08;默认在/dev的sr0&#xff09; 3.将光盘文件挂载&#xff08;挂载后才可读取&#xff09; 为方便每一次开机之后自动挂载&#xff…

jQuery 笔记13 JavaScript的好帮手

相关内容&#xff1a;下载jQuery网址、jQuery的使用、表格排序软件&#xff08;tablesorter&#xff09;、行事历软件&#xff08;FullCalendar&#xff09;、…… jQuery是一套开放性源代码的JavaScript函数库(Library)&#xff0c;jQuery是JavaScript函数库&#xff0c;简化了…

《21天学通C++》(第十二章)运算符类型与运算符重载

1.为什么要重载运算符&#xff1f; 通过重载运算符&#xff0c;可以将复杂的操作封装成简单的运算符形式&#xff0c;简化代码&#xff0c;提高可读性下面举一个简单的例子 计算两个点的坐标之和。 1.不重载运算符 #include <iostream> using namespace std; class P…

JavaScript基础(四)

逻辑运算符 && 与 : 多个条件同时满足 ΙΙ 或 : 多个条件满足一个 &#xff01; 非 : 否定某个条件 例: <script> //&多个条件同时满足&#xff0c;才返回true //任意一个为false&#xff0c;就返回false var a 10; var b 20; …

【linux】重定向

重定向 什么是重定向如何实现一个简单的重定向关于重定向的系统调用接口 注意&#xff1a;在看这篇博客之前&#xff0c;最好是要对文件在系统中是如何被打开的以及操作系统是如何管理文件有一个初步了解&#xff0c;如果不了解的话&#xff0c;可以看看这篇博客《初步认识文件…

stm32之hal库spi驱动封装(实现阻塞,中断,dma三种方式)

前言 配置功能参考rt-thread驱动代码将中断配置和dma配置单独分开管理 代码 中断管理 头文件 /** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-5-3 shchl first version*/#ifnd…

【AIGC】本地部署 ollama + open-webui

在之前的篇章《【AIGC】本地部署 ollama(gguf) 与项目整合》中我们已经使用 ollama 部署了一个基于预量化&#xff08;gguf&#xff09;的 Qwen1.5 模型&#xff0c;这个模型除了提供研发使用外&#xff0c;我还想提供给公司内部使用&#xff0c;因此还需要一个 ui 交互界面。 …

2003-2022年各省对外直接投资存量/省对外直接投资流量/省OFDI流量/省OFDI存量数据

2003-2022年各省对外直接投资存量、省对外直接投资流量、省OFDI流量、省OFDI存量数据 1、时间&#xff1a;2003-2022年 2、来源&#xff1a;对外直接投资公报 3、范围&#xff1a;31省 4、指标&#xff1a;省对外直接投资流量/OFDI流量、省对外直接投资存量/OFDI存量 5、指…

OpenCV(三)—— 车牌筛选

本篇文章要介绍如何对从候选车牌中选出最终进行字符识别的车牌。 无论是通过 Sobel 还是 HSV 计算出的候选车牌都可能不止一个&#xff0c;需要对它们进行评分&#xff0c;选出最终要进行识别的车牌。这个过程中会用到两个理论知识&#xff1a;支持向量机和 HOG 特征。 1、支…

爬虫自动化之drissionpage实现随时切换代理ip

目录 一、视频二、dp首次启动设置代理三、dp利用插件随时切换代理一、视频 视频直接点击学习SwitchyOmega插件使用其它二、dp首次启动设置代理 from DrissionPage import ChromiumPage, ChromiumOptions from loguru

MySQL与金蝶云星空对接集成执行查询语句-v2打通销售退货新增V1

MySQL与金蝶云星空对接集成执行查询语句-v2打通销售退货新增V1 数据源系统:MySQL mysql是一个关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;所谓的关系型数据库&#xff0c;是建立在关系模型基础上的数据库&#xff0c;借助于集合代数等数学概念和方法来处理数…

深度解析 Spring 源码:探寻Bean的生命周期

文章目录 一、 Bean生命周期概述二、Bean生命周期流程图三、Bean生命周期验证3.1 代码案例3.2 执行结果 四、Bean生命周期源码4.1 setBeanName()4.2 setBeanFactory()4.3 setApplicationContext()4.4 postProcessBeforeInitialization()4.5 afterPropertiesSet()4.6 postProces…

npm安装依赖报错解决办法

项目场景&#xff1a; 安装gitee上的开源vue3TS项目&#xff0c;npm安装依赖报错 问题描述 克隆项目到VSCode之后&#xff0c;使用npm install安装依赖&#xff0c;报错 npm install npm ERR! code ENOENT npm ERR! syscall open npm ERR! path Y:\WebStudyBlog\MovieWeb/p…

【Linux】学习笔记

文章目录 [toc]第一章&#xff1a;基础篇01|课程介绍02|内容综述03|什么是Linux04|Linux的内核版本及常见发行版内核版本发行版本Red Hat Enterprise LinuxFedoraCentOSDebianUbuntu 05|安装VirtualBox虚拟机VirtualBox下载url 06|在虚拟机中安装Linux系统Linux安装镜像下载 07…

基于OpenCv的图像傅里叶变换

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

【C++并发编程】(四)条件变量

文章目录 &#xff08;四&#xff09;条件变量 &#xff08;四&#xff09;条件变量 条件变量&#xff08;Condition Variable&#xff09;用于线程间的同步&#xff0c;允许一个或多个线程在特定条件不满足时等待&#xff0c;并在条件满足时被其他线程唤醒。C标准库中提供了的…