C++类和对象:拷贝构造函数和运算符重载

news2024/9/24 6:22:01

目录

一. 拷贝构造函数

1.1 什么是拷贝构造函数

1.2 编译器默认生成的拷贝构造函数

1.3 拷贝构造函数特性总结

二. 运算符重载

2.1 运算符重载概述

2.2 比较运算符重载(>  >=  == <  <=)

2.2.1 >运算符的重载

2.2.2 ==运算符的重载

2.2.3 >=运算符的重载

2.2.4 <运算符的重载

2.2.5 <=运算符的重载

2.3 加减相关运算符的重载(+= 、++、-=、--、+、-)

2.3.1 +=运算符的重载

2.3.2 +运算符的重载

2.3.3 -=运算符的重载

2.3.4 -运算符重载

2.3.5 ++运算符的重载

2.3.6 --运算符的重载

2.4 赋值运算符重载函数

2.4 取地址及const取地址操作符重载

2.4.1 const成员

2.4.2 &操作符的重载


一. 拷贝构造函数

1.1 什么是拷贝构造函数

拷贝构造函数,是C++类的六个默认构造函数之一,其完成的功能是通过一个已有的类对象,创建并初始化一个新的同类类对象。

拷贝构造函数的函数名与类名相同,有且只有一个类型为本类对象引用的参数,没有返回值。且拷贝构造函数唯一的参数一般使用const修饰。

演示代码1.1以日期类为例,首先创建了一个类对象d1,再通过类对象d1创建了一个新的类对象d2,调用Print成员函数打印类中成员变量的值,可以看到,d1和d2中成员变量值相同。

调用拷贝构造函数创新新对象的语法为:类名  拷贝构造函数名(&对象名)。

演示代码1.1:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year, int month, int day)  //构造函数
	{
		_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, 2, 28);   //创建类对象,调用默认构造函数
	Date d2(d1);   //调用拷贝构造函数创建类对象

	d1.Print();
	d2.Print();

	return 0;
}
图1.1  演示代码1.1的运行结果

警告:拷贝构造函数的参数必须是引用,不可以是值,因为这会引发无穷递归。

从图1.2中可以看出,当采用对象值作为拷贝构造函数的参数时,每次创建形参都会引发一次拷贝构造函数的调用,程序会一直调用调用拷贝构造函数,永远不会执行函数体内部的语句。当然,某些编译器会将值作为拷贝构造函数的参数的错误检查出来。

图1.2  用值作为拷贝构造函数参数时的递归调用情况图解

1.2 编译器默认生成的拷贝构造函数

跟构造函数和析构函数一样,如果用户不显示地定义拷贝构造函数,那么编译器就会自动生成拷贝构造函数。编译器默认生成的拷贝构造函数完成的操作是将一个已存在的类对象的内容逐字节拷贝到新创建的对象中,这种拷贝方式叫浅拷贝(值拷贝)。

演示代码1.3的日期类Date中不显示定义拷贝构造函数,运行程序,用d1拷贝构造d2,可以看到,d1和d2的成员变量值依旧相同,这证实了编译器会生成默认的拷贝构造函数。

演示代码1.2:

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)  //构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()   //类成员变量打印函数
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 2, 28);   //创建类对象,调用默认构造函数
	Date d2(d1);   //调用编译器默认生成的拷贝构造函数创建类对象

	d1.Print();
	d2.Print();

	return 0;
}
图1.3  演示代码1.2的运行结果

问题:根据演示代码1.1和1.2的运行结果,用户显示定义的拷贝构造函数和编译的自动生成的拷贝构造函数完成一样的操作,那是否可以认为,用户显示定义的拷贝构造函数没有什么价值呢?

答案显然是否定的。

对于上面代码中定义的日期类,确实可以使用编译器默认生成的拷贝构造函数。但是,对于那些类对象涉及动态资源申请的类,就不可以使用编译器默认生成的拷贝构造函数。

演示代码1.3中定义了栈类Stack,其中成员变量int* _a用于动态资源申请,在类对象销毁时,编译器会自动调用析构函数~Stack()释放动态开辟的内存空间,如果此时用s1拷贝构造s2,那么s1和s2中的_a就会指向同一块内存空间,对s1和s2两次调用析构函数会对同一块动态开辟的内存空间多次释放,造成程序崩溃。这种情况就必须有用户显示定义拷贝构造函数,实现深拷贝。

演示代码1.3:

class Stack
{
public:
	Stack(int capacity = 10)   //构造函数 
	{
		_a = (int*)malloc(capacity * sizeof(int));
		if (nullptr == _a)
		{
			printf("malloc fail\n");
			exit(-1);
		}

		_capacity = capacity;
		_top = 0;
	}

	~Stack()  //析构函数,释放动态开辟的内存空间
	{

		free(_a);
		_a = nullptr;

		_capacity = _top = 0;
	}

	void Push(int x)  //压栈函数
	{
		_a[_top] = x;
		_top++;
	}

private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{
	Stack s1;  

	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	s1.Push(5);  //将1、2、3、4、5压入栈中

	Stack s2(s1);  //调用编译器默认生成的拷贝构造函数

	return 0;  //程序结束前两次调用析构函数
}
图1.4  演示代码1.3中的栈类对象的成员变量值及指向图解

1.3 拷贝构造函数特性总结

  1. 拷贝构造函数的函数名与类名相同。
  2. 拷贝构造函数是构造函数的一种重载形式。
  3. 拷贝构造函数没有返回值。
  4. 拷贝构造函数的参数有且只有一个,类型为本类对象的引用。
  5. 不能将值作为拷贝构造函数形参的类型,否则会引发无穷递归。
  6. 如果用户不显示定义拷贝构造函数,那么编译器就会默认生成拷贝构造函数。
  7. 对于存在动态资源申请的类,不可以使用编译器自动生成的拷贝构造函数。

二. 运算符重载

2.1 运算符重载概述

C++不允许直接对类对象使用运算符,但是,有些时候我们需要对类对象的成员进行相关操作,如:比较两个日期的先后(判断d1 > d2是否成立)、计算当天之后的第n天的日期(d2 = d1 + day)。为了增强程序的可读性,C++引入了运算符重载。

运算符重载是具有特殊函数名的函数,其具有一般函数公有的返回值、参数列表和函数名。(注意区分,构造函数、析构函数和拷贝构造函数没有返回值)。

运算符重载函数原型:返回值类型 operator运算符(参数列表)。

关于运算符重载的几点注意事项:

  1. 不能通过operator后接非运算符来创建新操作符,如operator$、operator@ 。
  2. 运算符必须有一个一个类类型参数。
  3. 不能改变运算符原本的含义。
  4. 参数列表的参数个数必须与运算符的操作数个数相同。
  5. 有五个操作符(sizeof、::、. 、.* 、?:)不能进行重载。

特别注意:在类对象中定义和声明运算符重载,会存在一个隐含的this指针作为一个参数,this指针为运算符重载函数的第一个参数。

对于有两个操作数的运算符,运算符重载函数的第一个参数为左操作数,第二个参数为右操作数。

本章以日期类为例,对各种运算符的重载进行实现

演示代码2.1:(日期类成员变量及成员函数声明)

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1);  //默认构造函数
	int GetMonthDay(int year, int month);  //月份天数获取函数
	void Print();  //日期打印函数

	//1.比较类操作
	bool operator>(Date& d);
	bool operator>=(Date& d);
	bool operator==(Date& d);
	bool operator<(Date& d);
	bool operator<=(Date& d);

	//2.加减法类操作
	Date& operator+=(int day);  //日期加等函数
	Date operator+(int day);  //日期加法函数

	//前置++和后置++重载
	//后置++中采用一个int型的占位参数,用于表示后置
	Date& operator++();
	Date operator++(int);  

	Date& operator-=(int day);  //日期减等函数
	Date operator-(int day);  //日期减法函数

	Date& operator--();  //日期自减函数(前置)
	Date operator--(int);  //日期自减函数(后置)


	//日期间隔计算
	int operator-(Date& d);

	//星期打印函数
	void WeekPrint();

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

2.2 比较运算符重载(>  >=  == <  <=)

我们只需要实现>和==操作符的重载,那么>=  <=  <就都可以通过复用>和==运算符重载函数来实现重载。

2.2.1 >运算符的重载

依次比较this指针指向的类的年、月、日是否大于被比较对象即可。 

bool Date::operator>(Date& d)  //判断大于
{
	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;
	}
}

2.2.2 ==运算符的重载

年月日均相等返回值为true,否则为false。

bool Date::operator==(Date& d)
{
	return (_year == d._year) && (_month == d._month) && (_day == d._day);
}

2.2.3 >=运算符的重载

d1>d2和d1==d2其中之一成立即d1>=d2成立,*this代表类对象d1。

bool Date::operator>=(Date& d)
{
	return (*this > d) || (*this == d);
}

2.2.4 <运算符的重载

d1>d2 和 d1==d2 均不成立即 d1<d2 成立。

bool Date::operator<(Date& d)
{
	return !((*this > d) || (*this == d));
}

2.2.5 <=运算符的重载

d1>d2 和 d1==d2 其中之一成立即d1<=d2成立。

bool Date::operator<=(Date& d)
{
	return (*this < d) || (*this == d);
}

2.3 加减相关运算符的重载(+= 、++、-=、--、+、-)

2.3.1 +=运算符的重载

对日期类进行+=操作,就是获取当前日期再过day天后的日期。其计算方式为在当前_day上加day,如果大于当前_month天数就向_month进位,如果_month大于12就向年_year进位。

int Date::GetMonthDay(int year, int month)
{
	static int MonthDayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int day = MonthDayArray[month];

	//判断闰年,2月天数+1
	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		day += 1;
	}

	return day;
}

Date& Date::operator+=(int day)  //日期加等函数
{
	_day += day;
	int MonthDay = 0;

	while (_day > (MonthDay = GetMonthDay(_year, _month)))
	{
		_day -= MonthDay;
		_month++;   //天数大于当前月份天数就向月进位

		if (_month == 13)  //向年进位
		{
			_month = 1;
			_year++;
		}
	}

	return *this;
}

2.3.2 +运算符的重载

+运算符不改变被加数的值,+=运算符改变被加数的值,+仅返回做加法后的值,不改变被加数本身。因此我们只需要拷贝构造一份*this对象ret,然后对ret执行+=操作即可。

Date Date::operator+(int day)  //日期加法
{
	Date ret(*this);  //调用拷贝构造函数,创建返回值
	ret += day;
	return ret;
}

2.3.3 -=运算符的重载

计算当前日期向前day天的日期。首先让_day -= day,如果_day<0,就向月借位,如果_month==0成立,就向年借位,直到_day>0终止。

Date& Date::operator-=(int day)  //日期减等函数
{
	_day -= day;

	while (_day <= 0)
	{
		_month--;  //如果当前天数小于0,向月借位
		if (_month == 0)  //月为0向年借位
		{
			_year--;
			_month = 12;
		}

		_day += GetMonthDay(_year, _month);  //日期更新
	}

	return *this;
}

2.3.4 -运算符重载

与+运算符类似,-运算符不改变被减数的值,-=运算符改变被减数的值,-仅返回做减法后的值,不改变被减数本身。因此我们只需要拷贝构造一份*this对象ret,然后对ret执行-=操作即可。

Date Date::operator-(int day)  //日期减法函数
{
	Date ret(*this);  //拷贝构造创建返回值
	ret -= day;
	return ret;
}

2.3.5 ++运算符的重载

++运算符分为前置++和后置++,C++通过引入一个int型的占位参数来区分后置++和前置++,后置++需要占位参数。

  • 前置++函数声明:Date& operator++()
  • 后置++函数声明:Date& operator++(int)
Date& Date::operator++()  //日期前置++
{
	(*this) += 1;
	return *this;
}

Date Date::operator++(int)  //日期后置++
{
	Date ret(*this);
	(*this) += 1;
	return ret;
}

2.3.6 --运算符的重载

--与++类似,需要一个int型的占位参数区分前置和后置--。

  • 前置--函数声明:Date& operator--()
  • 后置--函数声明:Date& operator--(int)
Date& Date::operator--()  //日期自减函数(前置)
{
	(*this) -= 1;
	return *this;
}

Date Date::operator--(int)  //日期自减函数(后置)
{
	Date ret(*this);
	(*this) -= 1;
	return ret;
}

2.4 赋值运算符重载函数

赋值运算符重载函数为C++类的六个默认成员函数之一,如果用户不显示定义,那么编译器就会自动生成赋值运算符重载函数。赋值运算符重载函数的返回值类型为类对象的引用,参数有且只有一个,类型也为类对象的引用。

  • 函数参数类型:const 类名& 
  • 函数返回值类型:类名&
  • 返回值:*this -- 为了满足=运算符可以连续赋值的特性
  • 系统自动生成的赋值函数执行的操作为逐字节赋值

演示代码2.2中显示定义了赋值运算符重载函数,并在主函数中执行连续赋值操作,观察程序运行结果,d1、d2、d3都被赋予了d1的值,可见连续赋值成功。

演示代码2.2:

class Date  //日期类
{
public:
	Date(int year = 0, int month = 1, int day = 1)  //默认构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

	//赋值运算符重载函数
	Date& operator=(const Date& date)
	{
		_year = date._year;
		_month = date._month;
		_day = date._day;

		return *this;
	}

	void Print()  //日期打印函数
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2023, 2, 25);
	Date d2(2023, 2, 15);
	Date d3;

	d3 = d2 = d1;   

	cout << "d1: ";
	d1.Print();
	cout << "d2: ";
	d2.Print();
	cout << "d3: ";
	d3.Print();

	return 0;
}
图2.1  演示代码2.2的运行结果

警告:赋值运算符重载函数只能在类的内部定义,不能在类的外部定义为全局函数。

这是因为:如果用户不再类内部显示定义赋值运算符重载函数,那么编译器就会默认生成一个赋值运算符重载函数,这样编译器自动生成的赋值运算符重载函数和用户在类外部自定义的赋值运算符重载函数就会发生冲突。

2.4 取地址及const取地址操作符重载

2.4.1 const成员

假设定义一个const属性的类对象const Date d1,那么如果直接调用d1.Print()会发生报错。这是因为,隐含的this指针参数类型为Date* const this,而&d1的类型为const Date* const,传参时存在权限放大问题。这时,只需要在Print函数的声明后面添加const即可,这里的const的功能是将this指针的参数类型由Date* const转变为const Date* const。

//head.h
#pragma once
#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1);

	//如果不用const对成员函数进行修饰,那么就无法打印const date的类对象
	//const修饰改变this指针的类型
	//Date* const this -> const Date* const this
	void Print() const;   //const成员函数

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


//Date.cpp
#include "head.h"
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

void Date::Print() const  //const成员函数
{
	cout << _year << "-" << _month << "-" << _day << endl;
}


//test.cpp
#include "head.h"
int main()
{
	const Date d1(2023, 2, 28);
	d1.Print();  //调用const成员函数 2023-2-28
	return 0;
}

2.4.2 &操作符的重载

&操作符重载函数分为对普通对象取地址和对const对象取地址,一般不需要用户来实现。

演示代码2.3:

//如果用户不自定义,那么编译器会自动生成取地址运算符重载操作符
//取地址重载一般不会由用户自主实现
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	Date* operator&()  //普通对象的取地址操作符运算重载
	{
		return this;
	}

	const Date* operator&() const   //对于const对象的取地址运算符重载
	{
		return this;
	}

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

int main()
{
	Date d1(2023, 2, 27);
	cout << &d1 << endl;

	const Date d2(2023, 2, 28);
	cout << &d2 << endl;

	return 0;
}
图2.2  演示代码2.3的运行结果

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

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

相关文章

面对海量的监控视频数据应该如何存储?

面对有些行业及工作特殊性&#xff0c;监控摄像头是必不可免的&#xff0c;面对成千上万的摄像头&#xff0c;每时每秒产生的视频数据&#xff0c;选择一个合理的存储方式&#xff0c;将会为您节省一大笔费用。而且&#xff0c;有些监控摄像头视频数据还需要按照国家要求存储30…

SpringCloud OpenFeign 源码分析

前言 由于公司正在高sky迁移&#xff0c;我们部门的老应用SpringBoot 1.x升级2.x&#xff0c;其中老的Neflix Feign也升级成了Spring Cloud OpenFeign&#xff0c;由于业务条线的各种高低版本以及服务之间调用等存在一些兼容性问题&#xff0c;于是看了下OpenFeign的源码&#…

【Web逆向】某津市公共资源交易平台链接加密分析

【Web逆向】某津市公共资源交易平台链接加密分析声明一、起因二、开始分析三、源码下载地址声明 本文章中所有内容仅供学习交流&#xff0c;相关链接做了脱敏处理&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 一、起因 好奇抓取 天津市公共资源交易平台 的…

这个WPF DataGrid组件,可以让业务数据管理更轻松!(Part 1)

DevExpress WPF的DataGrid组件是专用于WPF平台的高性能XAML网格控件&#xff0c;该组件附带了几十个具有高影响力的功能&#xff0c;使开发者可以轻松地管理数据并根据也无需要在屏幕上显示数据。PS&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚…

Telerik JustMock 2023 R1 Crack

Telerik JustMock 2023 R1 Crack 制作单元测试的最快、最灵活和模拟选项。 Telerik JustLock也很简单&#xff0c;可以使用一个模拟工具来帮助您更快地生成更好的单元测试。JustLock使您更容易创建对象并建立对依赖关系的期望&#xff0c;例如&#xff0c;互联网服务需求、数据…

常用的xpath

一、xpath 语法 简单看一下菜鸟教程即可 1、基本语法 XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式&#xff1a; 表达式描述nodename选取此节点的所有子节点。/从根节点选取&#xff08;取子节点&#…

数据挖掘(1)--基础知识学习

前言 自20世纪90年代以来&#xff0c;随着数据库技术应用的普及&#xff0c;数据挖掘&#xff08; Data Mining &#xff09;技术已经引起了学术界、产业界的极大关注&#xff0c;其主要原因是当前各个单位已经存储了超大规模&#xff0c;即海量规模的数据&#xff0c;未来能够…

【设计模式】5.原型模式

概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 结构 原型模式包含如下角色&#xff1a; 抽象原型类&#xff1a;规定了具体原型对象必须实现的的 clone() 方法。具体原型类&#xff1a;实现抽象原型类的 clone() 方…

【IP技术】ipv4和ipv6是什么?

IPv4和IPv6是两种互联网协议&#xff0c;用于在互联网上标识和寻址设备。IPv4&#xff08;Internet Protocol version 4&#xff09;是互联网协议的第四个版本&#xff0c;是当前广泛使用的互联网协议。IPv4地址由32位二进制数构成&#xff0c;通常表示为4个十进制数&#xff0…

使用python测试框架完成自动化测试并生成报告-实例练习

练习一: 使用unittest 完成自动化测试并使用HttpTestRunner生成报告 1、写个简单的计算器功能&#xff0c;大小写转换功能&#xff0c;随机生成字符串功能 2、编写测试用例&#xff0c;不同的数据&#xff08;你能想到的所有测试用例&#xff09;&#xff0c;并进行断言。除0的…

GitHub 标星 15w,如何用 Python 实现所有算法?

学会了 Python 基础知识&#xff0c;想进阶一下&#xff0c;那就来点算法吧&#xff01;毕竟编程语言只是工具&#xff0c;结构算法才是灵魂。 新手如何入门 Python 算法&#xff1f; 几位印度小哥在 GitHub 上建了一个各种 Python 算法的新手入门大全。从原理到代码&#xf…

蒸汽波风格图不会画?AI作画帮你秒级出图

在最近几年&#xff0c;AI图像生成技术在视觉艺术领域得到了广泛应用&#xff0c;可以通过数据和机器学习技术来创作出非常有趣的艺术品。今天我就带来的图片风格是&#xff1a;蒸汽波混搭二次元。 蒸汽波混搭二次元图像的创作&#xff0c;大都是以现有的二次元图像作为基础&a…

配置CentOS 7

1&#xff1a;配置CentOS71.1&#xff1a;安装需注意如果出现类似提示&#xff0c;勾选复选框&#xff0c;并点击确定。1.2&#xff1a;选择安装项选择开始安装后&#xff0c;需等待….1.3&#xff1a;选择语言1.4&#xff1a;安装信息摘要大部分采用默认项设置自动分区网络设置…

筑基八层 —— 问题思考分析并解决

目录 零&#xff1a;移步 一.修炼必备 二.问题思考&#xff08;先思考&#xff09; 三.问题解答 零&#xff1a;移步 CSDN由于我的排版不怎么好看&#xff0c;我的有道云笔记相当的美观&#xff0c;请移步有道云笔记 一.修炼必备 1.入门必备&#xff1a;VS2019社区版&#x…

华为OD机试模拟题 用 C++ 实现 - 双十一(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明双十一题目输入输出示例一输入输出示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 …

Linux系统基础命令(一)

一、图形界面和终端界面 图形界面&#xff1a;是指采用图形方式显示的计算机操作用户界面。 终端界面&#xff1a;是指黑底白字的命令行界面。 什么是tty呢&#xff1f; tty&#xff1a;终端设备的统称。 tty一词源于Teletypes&#xff0c;或者teletypewriters&#xff0c;…

高精度真空度程序控制在真空解冻过程中的应用

摘要&#xff1a;为了解决目前各种真空冷冻过程中存在的真空压力还是人工手动调节&#xff0c;无法进行可编程准确自动控制的问题&#xff0c;本文提出了具体解决方案。解决方案的基本原理是根据动态平衡法&#xff0c;具体实现是依据不同的真空压力设定值分别采用电动针阀调节…

WebRTC入门与提高-WebRTC原理(STUN/TURN/SDP)

1 WebRTC入门本章目的&#xff1a;&#xff08;1&#xff09;了解什么WebRTC&#xff08;2&#xff09;掌握WebRTC通话原理&#xff08;3&#xff09;学完该课程的收获1.1 什么是WebRTCWebRTC&#xff08;Web Real-Time Communication&#xff09;是 Google于2010以6829万美元从…

华为OD机试模拟题 用 C++ 实现 - 旋转骰子(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明旋转骰子题目输入输出示例一输入输出示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。…

C++ Primer Plus 第6版 读书笔记(3) 第3章 处理数据

目录 3.1 简单变量 3.1.1 变量名 *位与字节 3.1.4 无符号类型 3.1.7 C如何确定常量的类型 C是在 C 语言基础上开发的一种集面向对象编程、泛型编程和过程化编程于一体的编程语言&#xff0c;是C语言的超集。本书是根据2003年的ISO/ANSI C标准编写的&#xff0c;通过大量短…