C++——类和对象3

news2024/11/16 7:34:46

目录

1. 运算符重载

1.1 "==" 的重载

1.2 前置 "++" 和后置 "++" 重载

1.3 流插入 "<<" 和流提取 ">>" 重载 

1.4 运算符重载注意事项

2. const成员和static成员 

2.1 const成员

2.2 static成员 

3. 友元 

3.1 友元函数 

3.2 友元类

4. 内部类 


1. 运算符重载

对于 + - * / 这类运算符,内置类型如int char等都可以支持运算,但一个类直接使用这些运算符的行为是未定义的,C++为了增强代码的可读性引入了运算符重载,使得我们的自定义类型可以像内置类型一样使用这些运算符

运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型返回值类型 operator操作符(参数列表

1.1 "==" 的重载

运算符重载函数可以写在类的外面(麻烦,不推荐),也可以写在类内部作为成员函数,比如要重载运算符 == ,可以写成

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

    // == 的运算符重载
    // 下面的实现等价于 bool operator==(Date* this, Date d2)
    bool operator==(Date d)   // 这里第一个参数是隐含了的this指针,指向d1,传进来是d2是第二个参数
	{
		return (_year == d._year)
			&& (_month == d._month)
			&& (_day == d._day);
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2000, 1, 2);
	Date d2(2008, 8, 8);

	d1 == d2;   // == 用于判断两个日期是否相等,但需要我们对运算符 == 重载后才能使用
    // d1.operator==(d2) 实际上是这种形式

	return 0;
}

1.2 前置 "++" 和后置 "++" 重载

“++” 是一个很特殊的运算符,它分为前置 ++ 和后置 ++ ,对于内置类型完成 +1的操作,区别在于它的返回值不同,如对于int类型: i++ 和 ++i 是不一样的,前者返回 i ,然后 i 自增1;后者 i 先自增1,然后返回自增之后的值(i + 1)

根据运算符重载的规则,前置++和后置++的重载形式

前置++:自定义类& operator++()
后置++:自定义类  operator++()

// 以Date类为例,可写为
Date& operator++()
Date  operator++()

但上面的形式无法区分,我们可以对其进行处理,使用重载将这两个函数区分开来

前置++
Date& operator++()

后置++ (增加一个int参数跟前置++构成重载进行区分)
Date  operator++(int) // 这里规定用int ,也可用形参int i接收
class Date
{
public:
	Date(int year = 2000, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	Date& operator+=(int day)
	{
        // +=函数重载的逻辑
	}

	// 前置++
	Date& operator++()   
	{
		*this += 1;        // 对象++
		return *this;      // 返回++后的对象
	}

	// 后置++
	Date operator++(int)
	{
		Date ret = *this;  // 将原对象保存一份
		*this += 1;        // 对象++

		return ret;        // 返回++前的对象
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2000, 1, 2);
	Date d2(2008, 8, 8);

	++d1; // d1.operator++(&d1);
	d2++; // d2.operator++(&d2,0)

	return 0;
}

在Linux下,通过反汇编查看后置++重载中默认传入int值,发现call函数<_ZN4DateppEi>时,的第二个参数寄存器里存的是 0 ,因此默认传过去的值为int 0

 400508:	48 89 c7             	mov    %rax,%rdi
  40050b:	e8 24 00 00 00       	callq  400534 <_ZN4DateC1Eiii> // call默认构造
  400510:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
  400514:	be 00 00 00 00       	mov    $0x0,%esi               // 第一个参数 int 0
  400519:	48 89 c7             	mov    %rax,%rdi               // 第二个参数 &d
  40051c:	e8 51 00 00 00       	callq  400572 <_ZN4DateppEi>   // call后置++

1.3 流插入 "<<" 和流提取 ">>" 重载 

C++的流插入运算符 “<<” 和流提取运算符 “>>” 是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream

C++类库中,istream类和ostream类对于内置类型的操作以成员函数的形式封装在类内部,能用来输出和输入C++标准类型的数据,我们的自定义类型是无法直接使用 “<<” 和 “>>” 进行输入输出的,因此必须进行重载才能使用

🔶 流插入运算符 “<<” 重载

C++库中流插入

arithmetic types (1)	
ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (long long val);
ostream& operator<< (unsigned long long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);

stream buffers (2)	
ostream& operator<< (streambuf* sb );

manipulators (3)	
ostream& operator<< (ostream& (*pf)(ostream&));
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));

先来看看对于内置类型,流插入运算符 “<<” 和流提取运算符 “>>”是怎么使用的,首先要了解std::cout在C++中是一个 ostream 类型的对象,因此实际上 “<<” 和 “+”一样,都存在左右操作数,<< 的左操作数是一个ostream类型的对象,右操作数可以是其他类型对象

int a = 10;
int b = 20;

 左操作数  运算符   右操作数
std::cout   <<        a;
    a        +        b;

由于 “<<” 运算符是作为输出数据使用的,传入的参数是输入型参数,无需对自定义类型的对象做修改,可以使用const传参,对 “<<” 重载的函数形式如下

ostream& operator<<(ostream &, const 自定义类 &)

因此,对于一个自定义类型的Date类,可以试着写一下流插入运算符的重载,将重载函数定义在类内作为成员函数,第一个参数是this指针,指向一个Date类型的对象,第二个参数是一个ostream类型的对象

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

	ostream& operator<<(ostream& cout)  // << 返回值仍是ostream类型,以便连续输出
	{
		return cout << _year << "年" << _month << "月" << _day << "日";
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2000, 1, 2);

    d1 << std::cout;      // 重载 << ,<<的左操作数是Date类型对象d1,右操作数是ostream类型对象std::cout
	// 正确输出 2000年1月2日

	return 0;
}

在上面的重载中,重载函数内部的 “<<” 是内置类型操作数,可以调用库中的 “<<” 做标准输出,我们的工作只是按照我们的设计对其进行了包装

d1 << std::cout;
等价于
d1.operator<<(std::cout);

但 d1 << std::cout; 这样的使用形式和平时的用法不同,我们渴望追求类似 std::cout << d1; 的形式,由于this指针总是作为成员函数的第一个参数存在,我们无法对左操作数进行调整,因此虽然建议运算符重载时定义成成员函数,但也可以在类外重载,作为全局函数

这里会遇到一个问题,在类外面定义的函数无法访问到类中的私有成员,可以使用自定义接口或者友元解决这个问题

最终实现的流插入运算符 “<<”重载为

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

	// 将 << 的重载声明成友元函数,这样外部的ostream& operator<<可以访问该类的私有成员变量
	friend ostream& operator<<(ostream& cout, const Date& d); // 声明
		
private:
	int _year;
	int _month;
	int _day;
};

inline ostream& operator<<(ostream& cout, const Date& d)
{
	return cout << d._year << "年" << d._month << "月" << d._day << "日";
}

int main()
{
	Date d1(2000, 1, 2);
	Date d2(2008, 8, 8); 

	std::cout << d1;

	return 0;
}

🔶 流提取运算符 “>>” 重载

C++库中流提取

arithmetic types (1)	
istream& operator>> (bool& val);
istream& operator>> (short& val);
istream& operator>> (unsigned short& val);
istream& operator>> (int& val);
istream& operator>> (unsigned int& val);
istream& operator>> (long& val);
istream& operator>> (unsigned long& val);
istream& operator>> (long long& val);
istream& operator>> (unsigned long long& val);
istream& operator>> (float& val);
istream& operator>> (double& val);
istream& operator>> (long double& val);
istream& operator>> (void*& val);

stream buffers (2)	
istream& operator>> (streambuf* sb );

manipulators (3)	
istream& operator>> (istream& (*pf)(istream&));
istream& operator>> (ios& (*pf)(ios&));
istream& operator>> (ios_base& (*pf)(ios_base&));

同样的,对于流提取运算符 “>>”,同样也有两个操作数,与 “>>” 的重载不同的是,“<<” 重载中传入的自定义类型对象要作为输出型参数,以键盘的输入对对象进行修改,因此不能传入const类型对象,要传入普通对象的引用,对 “<<” 重载的函数形式如下

istream& operator>>(istream &, 自定义类 &)
class Date
{
public:
	Date(int year = 2000, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
    
    // 同样作为友元
	friend istream& operator>>(istream& cin, Date& d);

private:
	int _year;
	int _month;
	int _day;
};

inline istream& operator>>(istream& cin, Date& d)   // 不能传const
{
	return cin >> d._year >> d._month >> d._day;
}

int main()
{
	Date d1(2000, 1, 2);
	Date d2(2008, 8, 8); 

	std::cin >> d1;

	return 0;
}

1.4 运算符重载注意事项

  • 不能通过连接其他符号来创建新的操作符:比如operator@(因为@原来就不是一个运算符)
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .*    ::   sizeof   ?:   . 注意以上5个运算符不能重载

2. const成员和static成员 

一个类中可以存在成员函数和成员变量,这些成员函数和变量可以有很多的关键字进行修饰,其中包括 const 和 static 这两个在C语言中用到过的关键字

2.1 const成员

在C语言中,const修饰的变量具有常量属性,不允许被修改,这一特性在C++中同样适用,但C语言中const不能用来修饰函数,C++中const可以用来修饰成员函数,也可以用来修饰对象

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针表明在该成员函数中不能对类的任何成员进行修改

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

    // void changeYear(Date* this)
	void changeYear()                     // 成员函数没有被修饰
	{
		_year = 2023; 
	}

    // void changeMonth(const Date* this) // 成员函数被const修饰
	void changeMonth() const
	{
		_month = 2;                       // 修改成员变量出错
	}

private:
	int _year;
	int _month;
	int _day;
};

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

问题一:const对象能调用非const成员函数

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

	void changeYear()   // 非const成员函数
	{
		_year = 2023; 
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	const Date d;       // const对象
	d.changeYear();     

	return 0;
}

不能

const对象的this指针为:const Date* this

非const成员函数中,第一个隐藏的参数接收的this指针类型为:Date* this

将const类型的指针作为参数传给非const类型的指针,会导致权限的放大,类型不匹配

问题二:非const对象能调用const函数

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

	const void changeYear()   // const成员函数
	{
		_year = 2023; 
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{ 
    Date d;             // 非const对象
	d.changeYear();     

	return 0;
}

可以

非const对象的this指针为:Date* this

const成员函数中,第一个隐藏的参数接收的this指针类型为:cosnt Date* this

将非const类型的指针作为参数传给const类型的指针,会导致权限的缩小,这是被允许的

问题三:const成员函数内可以调用其它的非const成员函数吗

不可以

在const成员函数内部调用其它的非const成员函数,需要将const成员函数的this传参给非const成员函数的this,相当于cosnt Date* this传给Date* this,导致权限的放大

问题四:非const成员函数内可以调用其它的const成员函数吗

可以

在非const成员函数内部调用其它的const成员函数,需要将非const成员函数的this传参给const成员函数的this,相当于 Date* this传给cosnt Date* this

2.2 static成员 

C++中,static关键字也可也用来修饰成员函数和成员变量 

用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化,生命周期是整个程序运行期间

class A
{
public:
	A()
		:_sval(1)      // 报错,无法通过构造函数初始化静态类数据
	{}

private:
	static int _sval;  // 仅仅是声明
};

正确的定义方式应该是 

class A
{
public:
	A(){}

private:
	static int _sval;  // 仅仅是声明
};

int A::_sval = 1;  // 类外定义,每个对象可见
注意写法,不用带static,直接  类型 + 类名::变量名 = 值

static成员变量不能在初始化列表进行初始化,因此也不能给它一个缺省值,为什么static成员变量不能在类内初始化呢? 

静态成员并不是属于某一个对象,而是属于整个类,如果在类内初始化,会导致每个对象都包含该静态成员,造成错误,因而类外定义和初始化是保证static成员变量只被定义一次的好方法

一个例外是,静态常量成员可以在类内初始化 

class A
{
public:
	A()
	{}

	void showStatic()
	{
		cout << _sval << endl;
	}

private:
	static const int _sval = 1;  // 可以通过这种方式初始化,但不能写进构造函数
};

因为加上const修饰之后,静态变量_sval已经不允许被修改,所有对象可以访问这个公有的变量但不能修改,也就是说这样的写法,也能保证_sval不属于某一个对象,而属于整个类

当静态成员为变量公有时,如果想访问静态成员变量,我们既可以用 <类型::静态成员变量> 访问,也可以用 <类对象::静态成员变量> 访问 

class A
{
public:
	A(){}

//private:
	static int _sval;  // 仅仅是声明
};
int A::_sval = 1;

int main()
{
	A a;
	cout << A::_sval << endl;  // 使用类型A或者A类的对象去访问_sval都可以
	cout << a._sval << endl;   // 前提是_sval在类里面是公有的

	return 0;
}

当静态成员变量是私有时,会受到访问限定符的限制,如何访问私有的静态成员变量呢?

一种很容易想到的方法是通过调用接口来访问,因为每个对象都可以访问到这个静态成员变量,另一种方法是 静态成员函数 

静态成员函数属于整个类,不属于某一个对象,因此没有this指针,只能访问静态的成员变量

class A
{
public:
	A()
		:_a(1)
	{}

	static int showMember()
	{
		cout << _a << endl;           // 报错:对非静态成员“A::_a”的非法引用
		return _sval;
	}

private:
	int _a;
	static int _sval;  // 仅仅是声明
};
int A::_sval = 1;      // 不在类外初始化会报链接错误

int main()
{
	A a;
	cout << A::showMember() << endl;  // 不需要通过对象,直接调用
    cout << a.showMember() << endl;   // 也可也通过对象调用

	return 0;
}

静态成员变量和普通的静态变量都存在静态区,生命周期也类似,那为什么要在类里定义一个静态成员变量而不去全局定义一个静态变量呢?

静态成员变量相比普通的静态变量的区别在于:只允许类内成员对变量做修改,可以用来统计一个类构造了多少对象(这里只是一种使用场景),静态成员函数不可以调用非静态成员函数, 非静态成员函数可以调用类的静态成员函数

static成员的特性

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

 

3. 友元 

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

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

3.1 友元函数 

在上面我们重定义了流插入和流提取两个运算符,为了使类外函数也能够访问到类内的私有成员,将类外的函数声明成这个类的友元函数,其形式是在类内给出一个函数声明,并用friend关键字修饰

class Date
{
    friend ostream& operator<<(ostream& cout, const Date& d); // 声明
    // ...
};

inline ostream& operator<<(ostream& cout, const Date& d)
{
	return cout << d._year << "年" << d._month << "月" << d._day << "日";
}

当一个函数被声明成某个类的友元函数时,并不意味着它变成了这个类的成员函数,因为没有this指针,所有也不能用const修饰,但它可以直接访问类的私有成员

🔶对于友元函数 

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

3.2 友元类

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

class A
{
	friend class B;            // 在A类内声明B类是我的友元                                                                   
                               // 此时B类可以访问A类中的私有
private:                       
	int _a;
};

class B
{                               // B类中没有把A类声明为友元
public:                         // A类无法访问B类私有
	void getClassA()    
	{
		cout << aa._a << endl;
	}
private:
	int _b;
	A aa;
};

🔶对于友元类

  • 友元关系是单向的,不具有交换性
  • 友元关系不能传递,如果B是A的友元,C是B的友元,则不能说明C时A的友元

 

4. 内部类 

内部类:如果一个类定义在另一个类的内部,这个在内部的类就叫做内部类

此时具有两种关系:

  • 内部类对外部类而言:内部类是一个独立的类,它不属于外部类,外部类不能通过对象去调用内部类,外部类对内部类没有任何优越的访问权限
  • 外部类对内部类而言:内部类是外部类的友元类,可以通过外部类的对象参数来访问外部类中的所有成员

简单来说就是内部类是外部类的友元,能访问外部类的私有,但受到外部类的类域限制

外部类不是内部类的友元,不能访问内部类成员

class A
{
public:
	A(int a = 1)
		:_a(a)
	{}

	class B                        // B是A的内部类,在A内定义
	{
	public:
		void getClassA(const A& a)        // 通过A类型对象之间访问私有
		{
			cout << a._a << endl;
		}
	private:
		int _b;
	};

private:
	int _a;
};

int main()
{
	A a;
    cout << sizeof(a) << endl;     // 4 内部类与外部类无关
	A::B b;                        // B收到A类域的限制,需要指定A::
	b.getClassA(a);

	return 0;
}

🔶对于内部类

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

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

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

相关文章

C++递推基础知识

文章目录一、递推的概念二、递推和递归的区别三、递推的实例1、最基础的&#xff1a;斐波那契数列2、变形版斐波那契数列3、较复杂的递推式求解&#xff1a;昆虫繁殖4、经典逆推问题&#xff1a;题目数量一、递推的概念 1、什么是递推算法&#xff1f; 递推算法&#xff1a;是…

剑指 Offer 60. n个骰子的点数

题目 把n个骰子扔在地上&#xff0c;所有骰子朝上一面的点数之和为s。输入n&#xff0c;打印出s的所有可能的值出现的概率。 你需要用一个浮点数数组返回答案&#xff0c;其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。 思路 动态规划&#xff1…

九龙证券|“股神”也做短线?巴菲特减仓逾八成台积电

美东时间2月14日盘后&#xff0c;“股神”巴菲特旗下公司伯克希尔哈撒韦&#xff08;下称“伯克希尔”&#xff09;发表的13F陈述引发商场热议。13F陈述被誉为“股市风向标”&#xff0c;出资者可藉此得以一窥华尔街大佬的最新出资思路。 根据美国证券交易委员会&#xff08;SE…

Vulnhub 渗透练习(三)—— Bulldog

环境搭建 下载链接 在 virtuallBox 中打开靶机。 virtuallBox 网络连接方式设置为仅主机。 vmware 设置桥接模式的网卡为 VirtualBox Host-Only Ethernet Adapter。 kail 网络适配设置为 NAT 和 桥接。 来自&#xff1a;https://blog.csdn.net/LYJ20010728/article/details/1…

JavaEE|文件操作·上

文章目录一、认识文件文件的概念文件的管理相关概念相对路径写法♋文件的分类Java中文件的操作二、File类的使用构造方法获得文件元信息判断的相关方法删除的方法与目录有关的方法修改名字三、流对象的使用什么是流文件内容操作涉及内容字节流对象InputStreamOutputStream字符流…

Bug bounty学习笔记20230213-0216(searching for Target)

www.bugcrowd.com Bug bounty program website 寻找email address Hunter.io Phonebook.cz www.voilanorbert.com – clearbit connect 在chrome里使用 Tools.verifyemailaddress.io Email-checker.net/validate 确定邮箱地址是不是真的 Dehashed.com Search for personal …

ChatGPT 最好的替代品

前两天我们邀请了微软工程师为我们揭秘 ChatGPT&#xff0c;直播期间有个读者问到&#xff1a;有了 ChatGPT&#xff0c;BERT 未来还有发展前途吗&#xff1f;我想起来最近读过的一篇博客“最好的 ChatGPT 替代品”。 不过聊到这俩模型&#xff0c;就不得不提到 Transformer。 …

夭寿啦!我的网站被攻击了了735200次还没崩

记得有一个看到鱼皮的网站被攻击&#xff0c;那时候我只是一个小小号&#xff0c;还在调侃&#xff0c;没想到我居然也有那么一天&#xff01; 突袭 一个风和日丽中午&#xff0c;我正在和同事吃饭&#xff0c;一个内存oom&#xff0c;我的小破站崩溃了。 虽然天天被攻击吧&a…

Linux - iostat 命令详解(监视磁盘 I/O)

iostat 是最常用的磁盘 I/O 性能观测工具&#xff0c;它提供了每个磁盘的使用率、IOPS、吞吐量等各种常见的性能指标&#xff0c;这些指标实际上来自 /proc/diskstats。 使用方式说明 [rootizwz98ahlvpkv3l7551ud2z ~]# iostat -help 用法:iostat [ 选项 ] [ <时间间隔>…

QML Gradient(渐变)

在Rectangle中简单的介绍了渐变&#xff0c;但只介绍了一种&#xff0c;下面还会介绍几种。 注意&#xff1a;渐变&#xff08;Gradient&#xff09;的优先级大于普通颜色&#xff08;color&#xff09; 线性渐变&#xff1a; 默认&#xff08;从上到下&#xff09;垂直渐变&…

C++【map和set的基本使用】

文章目录1、关联式容器2、键值对3、树形结构的关联式容器3-1、set3-1-1、set的使用3-1-3、set的使用样例3-2、map3-2-1、map的使用3-2-2、map的使用样例3-3、multiset3-4、multimap4、总结1、关联式容器 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如…

使用IPV6+DDNS连接内网主机

0、前言 IPV6已经普及多年&#xff0c;但是作为互联网用户好像并没有在实用性上有更多感受&#xff0c;或者说IPV6并没有让普通用户感觉到改变。我作为网络从业者其实也没有过多关注。在工作中普遍遇到的还是基于IPV4的网络&#xff0c;比如各个行业的网络、单位的内网区域和互…

C语言赋值(关系)运算符和逗号运算符

一.赋值&#xff08;关系&#xff09;运算符 1.关系运算符 高优先级组 < 左边值小于右边值,则返回1。否则返回0 < 左边值小于等于右边值,则返回1。否则返回0 > 左边值大于右边值,则返回1。否则返回0 > 左边值大于等于右边值,则返回1。否则返回0 低优先级组…

React组件的用法和理解

React组件 函数式组件 <div id"test"></div><script type"text/babel">//1.创建函数式组件(必须大写&#xff0c;函数必须有返回值)function MyComponent(){console.log(this); //此处的this是undefined&#xff0c;因为babel编译后开…

自己实现 ChatGpt ?先学习 Pytorch 吧

最近 ChatGpt 的爆火&#xff0c;让人非常震撼&#xff0c;无论是知识问答、对话还是代码撰写&#xff0c;都非常符合人们的预期&#xff0c;让人不得不感慨机器学习的强大。不信&#xff1f;看下面&#xff1a; 图1 语言分析处理 图2 知识问答 图3 写故事 图4 写代码 体…

详解ZabbixBSM是啥?业务服务监控达到全新高度

感谢本文译者赵广生 ! 欢迎更多资深用户&#xff0c;结合自己使用经验翻译原厂博文&#xff01; 赵广生 毕业于北京外国语大学&#xff08;信息管理与信息技术&#xff09;&#xff1b; 毕业后先后在多个公司从事信息化运维管理工作&#xff1b; 主要涉及虚拟化领域vmwa…

pytorch离线安装

windows下离线安装pytorch&#xff0c;很多内网机&#xff0c;无法连接外网&#xff0c;只能下载whl文件进行离线安装下载pytorch&#xff0c;地址https://download.pytorch.org/whl/torch_stable.html我是windows&#xff0c;Python37&#xff0c;没有gpu&#xff0c;所以选择…

如何利用知识库加强内部管理?

许多公司都知道需要有一个面向客户的知识库&#xff0c;以加强客户服务&#xff0c;提供更好的客户体验。 但是很多企业没有意识到的是&#xff0c;拥有一个内部知识库软件对于员工改善沟通和促进知识共享的重要性。 协作是组织成功的关键部分&#xff0c;通过明确的远景和使…

怎么看电脑显卡?3个步骤,1分钟学会

显卡作为电脑重要的组成部件&#xff0c;具有重要的作用。很多小伙伴买回来电脑后&#xff0c;想要查看电脑显卡&#xff0c;却不知道怎么看电脑显卡&#xff1f;别着急&#xff0c;今天小编就应各位小伙伴的要求&#xff0c;以图文的方式&#xff0c;3个步骤教你如何看电脑显卡…

C++设计模式(15)——代理模式

亦称&#xff1a; Proxy 意图 代理模式是一种结构型设计模式&#xff0c; 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问&#xff0c; 并允许在将请求提交给对象前后进行一些处理。 问题 为什么要控制对于某个对象的访问呢&#xff1f; 举个例子&…