【C++】——类和对象(构造函数,析构函数,拷贝构造函数,赋值运算符重载)

                                                  创作不易,多多支持! 

前言

相信你对这几个知识点有点混淆,相信看完以后,你会对此有一个清晰的认识。

一 类的6个默认成员函数

如果我们写一个类,但是类里面什么都没有,我们称之为空类。

其实这个类也不完全为空,因为编译器会类中自动生成这6个成员函数。

所以这几个成员函数也叫作默认成员函数,我们不去实现,编译器会生成。

接下来我们一个一个说明

二  初始化和清理

2.1  构造函数

1 .我们知道构造函数是执行初始化的操作,要是我们像以前一样写一个初始化函数去初始化也是可以的,下面用一个日期类去演示

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Date
{
public:
	void Init(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.Init(2024, 7, 5);调用函数初始化
	d1.Print();
	Date d2;
	d2.Init(2024, 7, 6);
	d2.Print();
	return 0;
}

从代码中我们可以看出 如果我们要初始化我们就需要每次都调用这个初始化函数,这就会显得非常的麻烦,那有没有更加便捷的方法呢?

构造函数是一种特殊的成员函数,函数名与类名相同不需要返回值,在类实例化时自动调用,每个类只调用一次,我们可以用这个自动调用的特性去让我们的初始化变的非常方便

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Date
{
public:
	Date()//无参构造函数
	{
		_year = 2024;
		_month = 7;
		_day = 5;
	}
	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;//调用无参
	Date d2(2024, 4, 24);调用有参
	d1.Print();
	d2.Print();
	return 0;
}

 在上面代码中我们并没有去调用里面的构造函数,我们可以看看输出的结果是什么

这里就体现了自动调用的特性。其中我们可以看出无参调用的时候有的人会这样写

Date d1();

这其实就错误了,因为编译器不知道你是调用函数还是类的实例化,所以不能这样写 

2. 对于构造函数因为是编译器默认生成的,所以即使我们不写,那么编译器也会自动生成一个,但是如果我们写了,那么编译器就不会生成了 

为了更好理解,下面给出相应代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Date
{
public:
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Print();
	return 0;
}

这串代码是不会报错的,因为编译器会自动生成一个默认的构造函数,这样在类实例化的时候会调用这个默认的构造函数

但是如果我们这样写

#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;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Print();
	return 0;
}

 可以看出这样就不行了,因为我们写了一个带参的构造函数,但是我们要初始化无参的就没了,因为我们写了构造函数,那么编译器就不会再生成默认的构造函数

但是不要想着编译器会给你那么方便,他虽然可以帮你自动调用,你没写也可以自动生成,但是它自动生成的默认构造函数是不会给你初始化的,这一点要尤其注意

我们可以看第一段代码, 是可以运行通过的,但是运行的结果却是

 可以看出结果不是我们想的那样,它并没有完成初始化,所以我们可以得出默认的构造函数对于内置类型是不处理的,内置类型就是(int/double/char...)之类的类型。

3.  那这个默认的构造函数没用吗?并不是,对于自定义类型,这个默认构造函数会去调用这个自定义类型的默认构造函数

可能这段话看起来非常绕,那下面我们看一点代码就清楚了

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Time
{
public:
	Time()//Time类的默认构造
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	//内置类型
	int _year;
	int _month;
	int _day;
	//自定义类型
	Time _t;
};
int main()
{
	Date d1;
	return 0;
}

 

之所以有这样一个结果就是在Date中有一个默认构造函数,这个是由编译器自动生成的,这个函数对于内置类型是不处理的,但是对于自定义类型,会去调用它的默认构造函数,所以就会打印出这个 Time()

4.  其实这让我们也非常难以接受,所以在后面c++又对它进行了补丁,可以在成员变量声明的时候给缺省值

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	void Print()
	{
		cout << _year <<'-'<< _month <<'-' << _day << endl;
	}
private:
	//内置类型
	int _year=2024;
	int _month=7;
	int _day=21;
	//自定义类型
	Time _t;
};
int main()
{
	Date d1;
	d1.Print();
	return 0;
}

注意这里虽然是在声明的时候给了值,但是这里并不代表是定义,也就是没有给空间,给空间还是要在实例化的时候给空间

5.  这里还有一个点要分清楚,默认成员函数只包括(全缺省构造函数,无参构造函数,我们没写编译器默认生成的构造函数)对于不是这些类型的都不能算是默认构造函数

所以如果我们写一个无参的构造函数,再写一个全缺省的构造函数,那么这个编译器就会报错,因为再类实例化的时候,它不知道调用哪一个,这一点也是要注意的

2.2 析构函数

析构函数也是特殊的成员函数 ,他和构造函数相反,他是负责清理的,但是两者的特性是差不多的 对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

 析构函数特性

1. 析构函数名是在类名前加上字符 ~
2. 无参数无返回值类型。
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构
函数不能重载
4. 对象生命周期结束时, C++ 编译系统系统自动调用析构函数

和构造函数一样,对于内置类型不处理,对于内置类型去调用它的析构函数

如果是对于这么日期类,里面只包含内置类型,那么也可以不写析构函数,因为出了作用域,内置类型的变量会随着栈的销毁而销毁 ,但是如果涉及到申请资源那么就需要用到析构函数了

#include<iostream>
using namespace std;

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;
}

这里和上面的构造函数一样,就不做太多的说明了。

三 拷贝复制

3.1 拷贝构造函数

 拷贝构造函数只有单个形参,该形参是对本类类型对象的引用一般用const修饰。

拷贝构造函数特性:

1.拷贝构造函数是构造函数的一种重载

2.拷贝构造函数的参数只有一个,而且这个形参必须是该类的引用,如果用传值会导致无穷递归

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	// Date(const Date& d)   // 正确写法
	Date(const Date d)   // 错误写法:编译报错,会引发无穷递归
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	return 0;
}

 在解释无穷递归的原因之前,我们得先来了解一下内置类型的拷贝和自定义类型的拷贝的区别

内置类型的拷贝就在底层就是一个字节一个字节的拷贝,也就是浅拷贝,那如果自定义类型也是浅拷贝的话,有可能会发生意想不到的后果

比如如果说自定义类型里面有申请空间开辟的数组,那么就会发生两次释放空间的问题

那如果避免这个问题了,这里我们就需要深拷贝,深拷贝就是再开辟一片空间,把他们分开,这样就不会导致重复释放了,所以这里我们就需要用拷贝构造函数去实现这一功能

所以我们对于自定义类型不管里面是不是有申请空间的变量,我们都去调用它的拷贝构造函数

 那么回到无穷递归这个问题,如果我们要拷贝自定义类型,那么编译器会去调用拷贝构造函数,那么就会传参,那么我们传参又会去调用新的拷贝构造,调用新的拷贝构造又会传参,那么就陷入无穷递归了

所以我们需要用到引用,但是这个引用我们不能去改变这个值,所以用const

所以拷贝构造函数的形式就是

Date(const Date& d)  
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

 其他的形式都不是拷贝构造

拷贝构造和构造函数也有点相似的地方,比如我们没有写拷贝构造函数的时候,编译器会去调用默认生成的拷贝构造,不过这个拷贝构造不会完成深拷贝,只是简单的值拷贝,也就是浅拷贝

3.2  赋值运算符重载

赋值运算符重载是具有特殊函数名的函数

函数名为:operator后面接需要重载的运算符符号(+,-,*,[])

函数原型:返回值类型 operator操作符(参数列表)

但是要注意有几个符号是不能重载的

.*   ::   sizeof   ?:   .

 还需要注意的是

1.不能通过连接其他符号来创建新的操作符:比如operator@
2.重载操作符必须有一个类类型参数
3.用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
4.作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐
藏的this

 1.运算符重载

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Date
{
public:
	bool operator==(const Date& d2)//运算符重载,这里只有一个参数
                                   //其实还有一个隐含的参数this
                                   //如果把该函数放在外面就没有this,但是就确保不了封装性了
	{
		return _year == d2._year
		&& _month == d2._month
		&& _day == d2._day;
	}
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1(2018, 9, 26);
	Date d2(2018, 9, 27);
	cout << (d1 == d2) << endl;
}
int main()
{
	Test();
	return 0;
}

上面的代码就是运算符重载的一个实例,那赋值运算符重载其实道理也大差不差

 但是其中也有些许细节

参数类型 const T& ,传递引用可以提高传参效率
返回值类型 T& ,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
检测是否自己给自己赋值
返回 *this :要复合连续赋值的含义

 按照上面的格式,我们可以写出一个相应代码

2. 赋值运算符重载

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Date
{
public:
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}
	Date(int year = 1900, 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;
	Date d2(2024, 7, 40);
	d1 = d2;
	d1.Print();
	d2.Print();
	return 0;
}

 3.赋值运算符重载只能定义成成员函数,不能定义成全局函数

因为运算符重载也是默认的成员函数所以,编译器会自己生成一个,那么我们自己如果在全局再写一个就会导致冲突,所以运算符重载必须写成成员函数,不能写成全局函数

class Date
{
public:
 Date(int year = 1900, int month = 1, int day = 1)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 int _year;
 int _month;
 int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
 if (&left != &right)
 {
 left._year = right._year;
 left._month = right._month;
 left._day = right._day;
 }
 return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员

4. 如果我们不写赋值运算符重载,那么编译器会自动生成一个,这个自动生成的对内置类型完成值拷贝,对于自定义类型会去调用对应类的赋值运算符重载

与拷贝构造函数类似,对于只有内置类型的类来说,写不写都可以,但是如果涉及到申请资源的变量那么就得自己写完成深拷贝的函数

5.  前置++与后置++重载

对于这两个直接看代码理解吧

class Date
{
public:
	
	Date& operator++()//前置++
	{
		_day += 1;
		return *this;
	}
	Date operator++(int)后置++
	{
		Date tmp = *this;
		_day+=1;
		return tmp;

	}
	Date(int year = 1900, 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形参去构成函数重载,这里只是构成重载没有任何作用

注意后置是先返回,后++,所以这得用一个临时对象保存,返回的时候不能用引用返回,因为返回的是临时对象,用引用返回会出现未定义行为

四  取地址重载

class Date
{ 
public :
 Date* operator&()//不加const
 {
 return this;
 }
 const Date* operator&()const//加const
 {
 return this ;
 }
private :
 int _year ; // 年
 int _month ; // 月
 int _day ; // 日
};

这里分为加const和不加const

 编译器默认生成的是不加const,所以一般这种重载我们不写交给编译器,但是如果有特殊的要求则需要自己手动写,比如想人获取指定的内容

const 成员函数 

用const修饰的成员函数称之为const成员函数,使用const修饰的成员函数不能修改类的成员变量,也不能调用非const成员函数

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

语法声明为:void fun() const;

class Date
{
public:
	void fun()const
	{
		_year = 6;//尝试对成员变量进行赋值
	}
	Date(int year = 1900, 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;
};

 

对于const对象调用const成员函数时,会调用const版本函数,而使用非const对象调用const成员函数时,会调用非const版本函数

这也就是一一对应

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Date
{
public:
	void fun()const
	{
		cout << "const" << endl;
	}
	void fun()
	{
		cout << "非const" << endl;
	}
	Date(int year = 1900, 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()
{
	const Date d1;
	Date d2;
	d2.fun();
	d1.fun();
	return 0;
}

可以看出结果也是一一对应的。

在这里还有一个点就是

🎈const成员函数不能调用非const成员函数,因为这是 权限放大

在const成员函数里它承诺了不能修改成员变量,如果去调用非const,非const又可以修改,这就违法了const成员变量的约定

🎈非const成员函数可以调用const成员函数,权限缩小是可以的

在非const可以修改也可以不修改,那在里面调用const成员函数,const成员函数规定不能修改,在非const里面并不矛盾,可以包容,所以是合理的

🎈const对象不可以调用非const成员函数

const对象里面的成员函数被隐式的看成了const成员函数,因此就和上面的道理是差不多的了

🎈非const对象可以调用const成员函数

 一句话就是,如果内部不涉及修改的,用const修饰,如果涉及修改的就不能加const

 

 相信看到这里,你会对构造函数,析构函数,拷贝构造函数,赋值运算符重载有一个更深的认识

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

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

相关文章

AWS SES发送邮件如何正确配置?操作指南?

AWS SES发送邮件有哪些限制&#xff1f;AWS SES发信的注意事项&#xff1f; AWS SES作为亚马逊云服务提供的一项高效、可靠的电子邮件发送服务&#xff0c;受到了众多企业的青睐。然而&#xff0c;如何正确配置AWS SES发送邮件。AokSend将详细解析AWS SES发送邮件的配置过程&a…

《苍穹外卖》Day07部分知识点记录

一、菜品缓存 减少查询数据库的次数&#xff0c;优化性能 客户端&#xff1a; package com.sky.controller.user;import com.sky.constant.StatusConstant; import com.sky.entity.Dish; import com.sky.result.Result; import com.sky.service.DishService; import com.sky…

搜维尔科技:如何选择最佳的xsens动作捕捉设备

xsens介绍 如何选择最佳的xsens动作捕捉设备 选择最佳的 Xsens 动作捕捉设置并不总是像我们希望的那样简单。根据每个人的情况&#xff0c;会有不同的选择、要求和挑战。 这就是我们创建此博客的原因&#xff1a;帮助您做出最适合您的决定。 您已经决定继续使用 Xsens 了吗…

电表抄表系统:现代能源管理的革新

1.界定和功能 电表抄表系统是一种前沿的自动化控制&#xff0c;用以远程控制搜集、解决与分析电表数据。它取代了传统的人工抄水表方法&#xff0c;提高了效率&#xff0c;降低了不正确&#xff0c;并且为供电公司带来了实时能源消耗信息。系统软件的主要作用包含全自动载入电…

大模型实战—通义千问大模型微调

通义千问大模型微调 在之前的文章中&#xff0c;我分享了一些使用大语言模型开发应用的方法&#xff0c;也介绍了几个开源大语言模型的部署方式&#xff0c; 有同学给我留言说想知道怎么训练自己的大语言模型&#xff0c;让它更贴合自己的业务场景。完整的大语言模型训练成本…

第十五届蓝桥杯省赛第二场PythonB组A题【进制】题解(AC)

解题思路 按照题意进行模拟&#xff0c;计算 x x x 的 b b b 进制过程中&#xff0c;若出现余数大于 9 9 9&#xff0c;则说明 x x x 的 b b b 进制一定要用字母进行表示。 x 8100178706957568def check(x, b):while x:if x % b > 10:return Falsex // breturn True…

Flink的安装、项目创建、任务打包和部署完整实现,任务实现使用JAVA语言

Flink资源下载地址 Flink安装包下载地址 一、本地模式安装Flink 1、在Linux服务上&#xff0c;创建flink文件夹 mkdir flink 2、上传文件并解压 tar -zxvf flink-1.14.6-bin-scala_2.11.tgz 解压完成后&#xff0c;如图&#xff1a; 3、启动Flink 进入到解压目录下&#x…

男士休闲裤比较好的品牌有哪些?高品质休闲男装推荐

穿衣服最重要的并不是要求多好看多时尚&#xff0c;相信绝大部分年纪在23岁以上的男同胞们更希望穿一些简约好搭配的款式&#xff0c;更重要的其实就是要求质量耐穿&#xff0c;以及有足够好的舒适性。 但是现在市面上的品牌实在是太多了&#xff0c;而且质量也参差不齐&#x…

【保姆级讲解下gateway基本配置】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

pwn--realloc [CISCN 2019东南]PWN5

首先学习一下realloc这个函数&#xff0c;以下是文心一言的解释&#xff1a; realloc是C语言库函数之一&#xff0c;用于重新分配内存空间。它的主要功能是调整一块内存空间的大小。当需要增加内存空间时&#xff0c;realloc会分配一个新的更大的内存块&#xff0c;然后将原内…

QT从入门到实战x篇_22_番外1_Qt事件系统

文章目录 1. Qt事件系统简介1.1 事件的来源和传递1.2 事件循环和事件分发1.2.1 QT消息/事件循环机制1.2.1.1 机制解释1.2.1.2 两个问题 1.2.2 事件分发 2. 事件过滤基础2.1 什么是事件过滤器&#xff08;Event Filter&#xff09;&#xff1f;2.2 如何安装事件过滤器 3. 事件过…

《QT实用小工具·四十》显示帧率的控件

1、概述 源码放在文章末尾 该项目实现了可以显示帧率的控件&#xff0c;项目demo演示如下所示&#xff1a; 、 项目部分代码如下所示&#xff1a; #ifndef FPSITEM_H #define FPSITEM_H#include <QQuickItem>class FpsItem : public QQuickItem {Q_OBJECTQ_PROPERTY(i…

制作自己的YOLOv8数据集

制作自己的YOLO8数据集 前言 该数据集的格式参照于coco数据集结构✨ 步骤一&#xff1a;收集图像数据 从互联网上下载公开的数据集&#xff0c;也可以使用摄像头或其他设备自行采集图像&#xff0c;确保你的图像数据覆盖了你感兴趣的目标和场景 步骤二&#xff1a;安装Labe…

提升工作效率必备,桌面待办事项提醒软件

在快节奏的现代社会&#xff0c;提升工作效率成为众多上班族的共同追求。有效的时间管理、合理的工作计划和正确的工具选择&#xff0c;是实现高效工作的三大关键。尤其是选择一款优秀的待办事项管理软件&#xff0c;能够极大地助力我们提升工作效率。 而我在网上找到了一款提…

11 - 在k8s官方文档上,经常搜索不到内容的问题

使用k8s官方文档时&#xff0c;会出现首页可以正常打开&#xff0c;但是输入搜索关键字之后&#xff0c;搜索不到内容的情况&#xff0c;如下图&#xff1a; 这是由于相关搜索组件被墙的原因&#xff0c;处理方法如下&#xff1a; 谷歌浏览器&#xff1a; 火狐浏览器&#x…

AI大模型重塑新媒体变现格局:智能写作技术助力腾飞!

文章目录 一、AI大模型&#xff1a;新媒体变革的引擎二、智能写作&#xff1a;内容生产的新范式三、精准推送&#xff1a;增强用户粘性的关键四、新媒体变现&#xff1a;插上AI翅膀的飞跃五、挑战与机遇并存&#xff1a;AI与新媒体的未来展望AI智能写作: 巧用AI大模型让新媒体变…

智慧园区引领未来产业趋势:科技创新驱动园区发展,构建智慧化产业新体系

目录 一、引言 二、智慧园区引领未来产业趋势 1、产业集聚与协同发展 2、智能化生产与服务 3、绿色可持续发展 三、科技创新驱动园区发展 1、创新资源的集聚与整合 2、创新成果的转化与应用 3、创新文化的培育与弘扬 四、构建智慧化产业新体系 1、优化产业布局与结构…

鸿蒙OpenHarmony【集成三方SDK】 (基于Hi3861开发板)

OpenHarmony致力于打造一套更加开放完善的IoT生态系统&#xff0c;为此OpenHarmony规划了一组目录&#xff0c;用于将各厂商的SDK集成到OpenHarmony中。本文档基于Hi3861开发板&#xff0c;向平台开发者介绍将SDK集成到OpenHarmony的方法。 规划目录结构 三方SDK通常由静态库…

C语言联合体详解

下午好诶&#xff0c;今天小眼神给大家带来一篇C语言联合体详解的文章~ 目录 联合体 1. 联合体类型的声明 2. 联合体的特点 代码一&#xff1a; 代码二&#xff1a; 3. 相同成员的结构体和联合体对比 ​编辑4. 联合体大小的计算 5. 联合体的优点 联合体 1. 联合体…

干货:html中的标签属性大全25个,收藏起来吧。

<meta> 元素是 HTML 中的一个标签&#xff0c;用于提供关于文档的元数据信息。它通常位于 <head> 标中&#xff0c;不会直接在页面上显示内容&#xff0c;而是用于告诉浏览器和搜索引擎一些关于页面的信息。 <meta charset"字符编码">&#xff1a;…