当前位置: 首页 > news >正文

C++学习记录——유 类和对象(3)

文章目录

  • 1、赋值运算符重载
    • 1、运算符重载
      • 1、理解
      • 2、运算符重载实例
    • 2、赋值运算符重载
  • 2、日期类的实现
    • 1、加减函数
      • 1、加函数
      • 2、减函数
    • 2、前/后置++--重载
    • 3.两个日期相减
  • 其他
    • 1、流插入
    • 2、流提取


日期类的整体实现代码: https://gitee.com/kongqizyd/start-some-c-codes-for-learning.c/tree/master/%E6%97%A5%E6%9C%9F%E7%B1%BB

关于日期类的讲解会比较长,可以边看完整代码边看分析

1、赋值运算符重载

1、运算符重载

1、理解

继续用日期类做例子。

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

假设现在要比较两个日期数值大小

int main()
{Date d1(2023, 2, 8);Date d2;return 0;
}

我们自然可以定义一个函数,参数类型就是Date类或者说Date的引用类,用来比较两个变量。但这样有些俗套了,或者说很常见的做法,C++有自定义类型和内置类型,内置类型的比较很简单,而自定义类型的比较需要程序员自己确定如何比较。C++对此有运算符重载函数,用到关键字operator。现在写一个比较相等的函数。

bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}

要把他当做一个正常的函数,并且d1和d2的位置也就是在main调用这个函数时的位置,d1 == d2即可调用。这里先把三个变量变成公有类型才能在外部访问。

d1 == d2;
operator==(d1, d2);

调用时这两种写法都可,不过第一个更简单。第一个对于程序,会及时地转换成operator==(d1, d2)。

但是如果想打印结果,不能用d1 == 2,因为实际写出来时,<< >>运算符优先级高于等于号,所以需要括起来。

现在是把这个函数放到全局里,所以类里的成员变量要换成公有的才行。而另一个办法就是把这个函数放到类里面也可,但如果直接放进去编译器就会告诉你参数放多了,因为本身是有this指针的,所以括号里放一个参数即可。

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

调用时这样写就行

cout << d1.operator==(d2) << endl;

运算重载特征:
不能通过连接其他符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
.* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出
现。

2、运算符重载实例

写一下小于的函数。

	bool operator<(const 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;elsereturn false;

当然也可以放到一块,直接就是return一串代码。

cout << d1.operator<(d2) << endl;

这样就可以检验一下结果。

不过我们还有一个更简单地写法。比如写小于等于的函数

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

大于等于

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

不能出现*this > d,编译器会报出一堆错。

在这里插入图片描述

2、赋值运算符重载

现在要把d2的值赋值给d1.

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

这里不用引用也可以,因为我们写好的拷贝构造函数是一个成熟的函数,用引用传参,而这里传参,调用完拷贝构造就好了,不过用一下引用能省点编译器工作。

但是这样不是赋值的完整函数。在C语言中,我们可以连续赋值,也就是x = y = z,如果按照这样写,一定会出错。这里的实现思路就是z赋值给y后要返回一个值,返回的这个值再赋值给x,这个返回值其实也就是y。

	Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}

还有一个问题,有可能会出现自己给自己赋值,所以加个判断。

		if (this != &d){_year = d._year;_month = d._month;_day = d._day;}

如果不写重载,编译器还是会自己生成,规则还是一样,有资源申请才需要自己写。

拷贝构造会这样写:
Date d2 = d1;
Date d2(d1);

重载需要一个Date类型的变量,而拷贝构造可以不需要,所以重载不能这样写,Date d2 = d1。

2、日期类的实现

现在写一个比较全的日期类。

<Date.h>

#pragma once
#include <iostream>
using namespace std;class Date
{
public:Date(int year = 2023, int month = 1, int day = 1);void Print();bool operator==(const Date& d);bool operator!=(const Date& d);bool operator<(const Date& d);bool operator<=(const Date& d);bool operator>=(const Date& d);bool operator>(const Date& d);//Date& operator=(const Date& d);private:int _year;int _month;int _day;
};

<Date.cpp>

#include "Date.h"Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}void Date::Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}bool Date::operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}bool Date::operator<(const 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;elsereturn false;
}bool Date::operator<=(const Date& d)
{return *this < d || *this == d;
}bool Date::operator>=(const Date& d)
{return !(*this < d);
}bool Date::operator>(const Date& d)
{return !(*this <= d);
}bool Date::operator!=(const Date& d)
{return !(*this == d);
}

<Test.cpp>

#include "Date.h"void Test1()
{Date d1(2023, 2, 8);d1.Print();Date d2(2023, 2, 28);d2.Print();
}int main()
{Test1();return 0;
}

针对初始化日期的函数,有一个现实问题没有想到,就是如果年是负数呢?或者其它数是一个不可能的数呢?所以要加上检查函数,比如上一篇的我GetDay等函数。

int GetMonthDay(int year, int month)
{int monthArr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31 };if (month == 2 && year % ((4 == 0 && year % 100 != 0) || (year % 400) == 0)){return 29;}else{return monthArr[month];}
}Date::Date(int year, int month, int day)
{if (month > 0 && month < 13 && (day > 0 && day <= GetMonthDay(year, month))){_year = year;_month = month;_day = day;}elsecout << "日期非法" << endl;
}

1、加减函数

1、加函数

写上相加的函数,这里的思路也和上一篇一样,有了返回值,+=也可以连续+=。如果这样写:Date d2 = d1 += 100,是会把d1也给改变。

Date& Date::operator+=(int day)
{_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if(_month == 13){++_year;_month = 1;}}return *this;
}
	Date d2 = d1;d2 += 100;d2.Print();d1.Print();

再写上+。

Date Date::operator+(int day)
{Date tmp(*this);tmp._day += day;while (tmp._day > GetMonthDay(tmp._year, tmp._month)){tmp._day -= GetMonthDay(tmp._year, tmp._month);tmp._month++;if (tmp._month == 13){++_year;tmp._month = 1;}}return tmp;
}
	Date d3 = d1 + 100;d3.Print();d1.Print();

用临时变量tmp,防止d1被改变。

出了作用域,*this存在,所以可以用引用,而tmp不存在,不能用引用。也可以在tmp前加上static,也不能用引用,d1为最一开始的数据,d2 = d1 + 100,没有问题,但是同样的,静态区里的这个tmp没有清除,它会接着上一次数据继续加,所以后面再来个d3 = d1 + 100就不是正确数据了。静态变量只会初始化一次,所以再次调用就不会被初始化。

+=和+的代码有些像,我们简化一下

Date Date::operator+(int day)
{Date tmp(*this);tmp += day;/*tmp._day += day;while (tmp._day > GetMonthDay(tmp._year, tmp._month)){tmp._day -= GetMonthDay(tmp._year, tmp._month);tmp._month++;if (tmp._month == 13){++_year;tmp._month = 1;}}*/return tmp;
}

+里面用+=。+=也可以使用+。

*this = *this + day;

不过实现+=,+里面放+=更好。因为+本身有拷贝,*this = *this + day还会有赋值。

2、减函数

减去天数,我们要往前倒月,倒年,先把年或者月给减好,然后再去获取天数。

Date& Date::operator-=(int day)
{_day -= day;while (_day <= 0){--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;
}

加减函数齐全后,有些问题就可以解决。d2 += -100,如果还是之前的代码,那么最终的结果不切实际,转换一下就是d2 -= 100,所以在每个函数开头,我们还需要加上判断。

Date& Date::operator+=(int day)
{//*this = *this + day;if (day < 0){*this -= -day;return *this;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if(_month == 13){++_year;_month = 1;}}return *this;
}

另外三个也是如此。

2、前/后置+±-重载

前置++比较简单,可以用引用,传入数据后+1,然后返回即可。

Date& Date::operator++()
{*this += 1;return *this;
}

后置++需要注意些,我们要返回一个+1之前的值,所以需要调用拷贝构造,创建一个临时变量。

Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}

至于编译器如何辨别是前还是后,这自有办法,不过为了构成重载,声明的时候后置会在括号里写上int,不必写变量名,仅供编译器区分用。实际比较起来,前置++还是更简单,不需要调用其他,一般情况下前置++用得比较多。

	Date& operator++();//前置++Date operator++(int);//后置++,int只是为了占位,和前置函数构成重载
void Test2()
{Date d1(2023, 2, 8);d1.Print();++d1;//前置正常++d1++;//后置会传一个形参类型的参数
}

–是这样写

Date& Date::operator--()
{*this -= 1;return *this;
}Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

测试的时候可以显式调用

d1.operator++(0);

3.两个日期相减

用int类型的减函数。

声明:int operator-(const Date& d);

int Date::operator-(const Date& d)
{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 n * flag;
}

测试代码

void Test5()
{Date d1(2023, 2, 8);d1.Print();Date d2(2002, 8, 4);d2.Print();cout << d1 - d2 << endl;
}

其他

1、流插入

像上面的Print函数,可不可cout打印呢?Print函数里是用cout实现的,那么可不可以直接cout << d1?实际上不行,但如果后面跟的是一个内置类型的变量,cout就可以了。C++有osream这个类,类里有cout等成员函数,但和默认成员函数不同,它们即使不写也有默认的函数,而其他成员函数就必须要写,ostream类已经写好了常用变量类型的函数重载,并且也写了<<的运算符重载,所以我们在用cout打印时不需要担心类型,因为C++已经写好了。

那么我们想用cout打印自定义类型的数据,那就需要自己写,写到自己的类里。

void Date::operator<<(ostream& out)
{out << _year << "年" << _month << "月" << _day << "日" << endl;
}

这样写出来,括号还是有两个参数,但是第一个参数是默认的*this,也就是外部声明的d1这些变量。运算符重载写的时候,要按照参数顺序写,所以最后就是d1 << cout。这样有些奇怪,不是我们平常见到的那样,那么把他从类里拿出来写就可以控制顺序了,但这样就会有一个问题,成员变量无法访问,除去把他们变公有外,还可以添加友元函数。

声明:void operator<<(ostream& out, const Date& d);

类里这样写

	//友元friend void operator<<(ostream& out, const Date& d);

定义:

void operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
}

测试代码

	operator<<(cout, d1);cout << d1;

平常写流插入的时候很多都是连续写,所以还需要改进,要有返回值。

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

2、流提取

流提取的参数不能加const,加const的作用是为了减少拷贝。

声明: istream& operator>>(istream& in, Date& d);
friend istream& operator>>(istream& in, Date& d);

定义

istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

测试代码

void Test7()
{Date d1;cin >> d1;cout << d1;
}

为了更简洁,我们可以用内联函数。实际上在类里面定义的成员函数,就默认为内联函数。那么Date.cpp文件里可以不写,把定义放到.h文件里,前面加上inline

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

本篇最一开始给的链接可以看到全部的代码,里面出现的const可以暂且不管,下一篇会写出为什么加const。

结束。

相关文章:

C++学习记录——유 类和对象(3)

文章目录1、赋值运算符重载1、运算符重载1、理解2、运算符重载实例2、赋值运算符重载2、日期类的实现1、加减函数1、加函数2、减函数2、前/后置--重载3.两个日期相减其他1、流插入2、流提取日期类的整体实现代码: https://gitee.com/kongqizyd/start-some-c-codes-for-learning…...

基于Hi3861平台的OpenHarmony程序是如何启动运行的

一、前言 在继续后面课程的内容讲解前&#xff0c;我们要知道在H3861平台上编写的代码到底是如何启动的&#xff0c;这一点很重要。 先分析HelloWorld程序的启动运行流程&#xff0c;并顺便讲解OpenHarmony在H3861平台的&#xff0c;系统是从哪里启动的。 反着推导函数之间具体…...

2023彻底解决Typora使用iPic微博图床失效问题

一、问题描述用Typora搭配iPic图床使用&#xff0c;最近csdn图片显示不出来用浏览器打开图片显示403&#xff0c;这里原因是微博图床出问题了导致的而使用iPic其他图床则需要一直付费&#xff0c;那有没有一劳永逸的解决所有问题呢&#xff1f;二、旧图恢复首先怎么找回旧图&am…...

Revit中添加水平仰视平面图及水平剖面

一、 Revit中如何添加水平仰视平面图 在Revit平面视图中视角是俯视视角&#xff0c;但是在一些特殊的情况下&#xff0c;我们可能需要创建仰视视角的平面视图&#xff0c;例如我们需要向上看天花板的灯具布置的时候。 1.下面讲一下如何在添加仰视平面视图的方法。如图1在模型中…...

Python 循环语句

Python的循环语句&#xff0c;程序在一般情况下是按顺序执行的。编程语言提供了各种控制结构&#xff0c;允许更复杂的执行路径。循环语句允许我们执行一个语句或语句组多次&#xff0c;下面是在大多数编程语言中的循环语句的一般形式&#xff1a;Python 提供了 for 循环和 whi…...

使用 ThreeJS 实现第一个三维场景(详)

文章目录参考描述index.html三维场景的基本实现导入 ThreeJS准备工作场景摄像机视锥体正交摄像机透视摄像机渲染器后续处理将摄像机添加至场景中移动摄像机设置画布尺寸将渲染器创建的画布添加到 HTML 元素中渲染物体结构材质合成将物体添加至场景中代码总汇执行效果动画reques…...

《小猫猫大课堂》三轮5——动态内存管理(通讯录动态内存化)

宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的很重…...

【Selenium学习】Selenium 八大定位法

1.1 ID定位HTML Tag 的 id 属性值是唯一的&#xff0c;故不存在根据 id 定位多个元素的情况。下面以在百度首页搜索框输入文本“python”为例。搜索框的 id 属性值为“kw”&#xff0c;如图1.1所示&#xff1a;代码如下&#xff0c;“find_element_by_id”方法已废弃&#xff0…...

算法训练营 day41 贪心算法 单调递增的数字 买卖股票的最佳时机含手续费

算法训练营 day41 单调递增的数字 买卖股票的最佳时机含手续费 单调递增的数字 738. 单调递增的数字 - 力扣&#xff08;LeetCode&#xff09; 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c…...

【数据结构-JAVA】排序

排序在现实生活中的应用可谓相当广泛&#xff0c;比如电商平台中&#xff0c;选购商品时&#xff0c;使用价格排序或是综合排序、高考填报志愿的时候&#xff0c;会参考全国大学排名的情况。下面介绍一些计算机中与排序相关的概念&#xff1a;排序&#xff1a;所谓排序&#xf…...

基于注解管理Bean

一、介绍从 Java 5 开始&#xff0c;Java 增加了对注解&#xff08;Annotation&#xff09;的支持&#xff0c;它是代码中的一种特殊标记&#xff0c;可以在编译、类加载和运行时被读取&#xff0c;执行相应的处理。开发人员可以通过注解在不改变原有代码和逻辑的情况下&#x…...

Containerd 的 Bug 导致容器被重建!如何避免?

作者简介邓宇星&#xff0c;SUSE Rancher 中国区软件架构师&#xff0c;6 年云原生领域经验&#xff0c;参与Rancher 1.x 到 Rancher 2.x 版本迭代&#xff0c;目前负责 Rancher For openEuler(RFO) 项目开发。最近我们关注到一个关于 containerd 运行时的 issue(​​https://g…...

win环境安装部署Jenkins

win环境安装部署Jenkins&#xff0c;2022年11月&#xff1a;从2022年 6 月 28 日发布的 Jenkins 2.357 和2022年9 月发布的 LTS 版本开始&#xff0c;Jenkins 需要 Java 11 才能使用&#xff0c;放弃 Java 8&#xff0c;如果用JDK1.8&#xff0c;那么Jenkins版本需要是2.357版本…...

网络变压器与不同芯片之间的匹配原则及POE通讯产品需要注意哪些方面

Hqst盈盛电子导读&#xff1a;网络变压器与不同芯片之间的匹配原则及POE通讯产品需要注意哪些方面网络变压器与不同芯片之间的匹配原则&#xff1a;一&#xff0c;电流型PHY芯片一般要配的网络变压器&#xff1a;1、变压器PHY侧3线共模电感 &#xff08;更适合POE产品&#xff…...

Spring WebFlux

目录 基于注解编程模型 函数式编程模型 传统的基于Servlet的Web框架,如Spring MVC,在本质上都是阻塞和多线程的,每个连接都会使用一个线程。在请求处理的时候,会在线程池中拉取一个工作者( worker )线程来对请求进行处理。同时,请求线程是阻塞的,直到工作者线程提示它已…...

C++基础面试题:new和malloc的区别

面试题&#xff1a;new和malloc的区别或new和malloc的异同 相同点&#xff1a; 1、new/delete和malloc/free它们都是内存申请和释放的函数。 2、new/delete和malloc/free 都要一一对应&#xff0c;调用了多少次new 就需要调用多少次delete&#xff1b;同 理调用多少次ma…...

WebDAV之葫芦儿·派盘+KMPlayer

KMPlayer 支持WebDAV方式连接葫芦儿派盘。 KMPlayer几乎可以播放您系统上所有的影音文件,支持几乎全部音视频格式。通过其强大的插件功能,可以支持层出不穷的新格式。软件还具有齐全的操控功能,支持捕获音频、捕获AVI、捕获画面、外挂字幕、自定义编辑设置,是视频爱好者的不…...

杨浦区人工智能及大数据(云计算)企业登记工作(2023年度)的通知

各相关单位&#xff1a; 根据《“长阳秀带”在线新经济产业集聚发展若干政策》&#xff08;杨府发〔2022〕2号&#xff09;及其实施细则的要求&#xff0c;现组织开展2023年度杨浦区人工智能与大数据(云计算&#xff09;企业登记备案工作,现将相关工作通知如下&#xff1a; 一…...

2023年去培训机构学前端还是Java?

选择专业肯定是优先考虑更有发展前景和钱途的专业。毕竟IT专业的培训费都不低&#xff0c;基本都要一两万左右&#xff0c;咱们花钱总是希望获得最大回报。 那么到底哪个更有发展前景呢&#xff1f; 零基础能学得会吗&#xff1f; 就业薪资如何呢&#xff1f; 前言 不知道大家有…...

【React】组件事件

React(二) 创建组件 函数组件 函数组件&#xff1a;使用JS的函数或者箭头函数创建的组件 使用 JS 的函数(或箭头函数)创建的组件&#xff0c;叫做函数组件约定1&#xff1a;函数名称必须以大写字母开头&#xff0c;React 据此区分组件和普通的 HTML约定2&#xff1a;函数组…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...