(c++)类和对象中篇

news2024/12/24 2:19:34

目录

1. 类的6个默认成员函数

2. 构造函数

3. 析构函数

4. 拷贝构造函数

5. 赋值运算符重载

6. const成员函数

7. 取地址及const取地址操作符重载


1. 类的 6 个默认成员函数
  • 如果一个类中什么成员都没有,简称为空类。
  • 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
  • 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。


2. 构造函数
2.1 概念

对于以下 Date 类:
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(2023, 9, 1);
     d1.Print();
     Date d2;
     d2.Init(2023, 9, 1);
     d2.Print();
     return 0;
}
  

          对于 Date 类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?

        构造函数 是一个 特殊的成员函数,名字与类名相同 , 创建类类型对象时由编译器自动调用 ,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次

2.2 特性
      构造函数 是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象

其特征如下:
  • 1.函数名与类名相同。
  • 2.无返回值。
  • 3.对象实例化时编译器自动调用对应的构造函数。
  • 4.构造函数可以重载。
  class Date
 {
  public:
      // 1.无参构造函数
      Date()
     {}
  
      // 2.带参构造函数
      Date(int year, int month, int day)
     {
          _year = year;
                    _month = month;
          _day = day;
     }
  private:
      int _year;
      int _month;
      int _day;
 };
  
  void TestDate()
 {
      Date d1; // 调用无参构造函数
      Date d2(2023, 9, 1); // 调用带参的构造函数
  
      // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
      // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
      // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
      Date d3();
 }
  • 5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦 用户显式定义编译器将不再生成。

  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类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函
数
     // 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再
生成
      // 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
     Date d1;
     return 0;
 }
  • 6. 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会 生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用??
  • C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类 型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型.

默认生成的构造函数:

  • 内置类型成员不做处理
  • 自定义类型成员会去调用它的默认构造函数

验证:

class Time
{
public:
     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 d;
     return 0;
}
注意: C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即: 内置类型成员变量在 类中声明时可以给默认值

class Time
{
public:
    Time()
     {
         cout << "Time()" << endl;
         _hour = 0;
         _minute = 0;
         _second = 0;
     }
private:
     int _hour;
     int _minute;
     int _second;
};

class Date
{
private:
     // 基本类型(内置类型)
     int _year = 1970;   //c++11允许的补丁
     int _month = 1;     //这里不是初始化,而是声明,给缺省值
     int _day = 1;       //给的是默认构造函数的缺省值

     // 自定义类型
     Time _t;
};

int main()
{
     Date d;
     return 0;
}
  • 7. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
  • 注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。


3. 析构函数

3.1 概念
析构函数:
  •          与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作
3.2 特性
析构函数 是特殊的成员函数,其 特征 如下:
  • 析构函数名是在类名前加上字符 ~
  • 无参数无返回值类型。
  • 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构 函数不能重载
  • 对象生命周期结束时,C++编译系统系统自动调用析构函数
  • 编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
  • 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

栈:

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 3)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}
	void Push(DataType data)
	{
		//...
		_array[_size] = data;
		_size++;
	}

	~Stack()
	{
		free(_array);
		//_array = nullptr;
		//_capacity = _size = 0;
	}

private:
	DataType* _array;
	int _capacity;
	int _size;
};

日期类对象:

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

	//~Date()
	//{
	//	//~Date()没有什么需要清理的
	//	cout << "~Date()" << endl;
	//}

	//内置类型析构函数不做处理
private:
	int _year;
	int _month;
	int _day;
};

自定义队列:

class MyQueue
{
public:
	//...

private:
	size_t _szie = 0;
	Stack _st1;
	Stack _st2;
};

关于以上三个函数的调用:

由此也可以总结出析构函数的特点:

a.内置类型不做处理

b.自定义类型成员会去调用它的析构函数


4. 拷贝构造函数

         拷贝构造函数 只有单个形参 ,该形参是对本 类类型对象的引用 ( 一般常用 const 修饰 ) ,在用 已存 在的类类型对象创建新对象时由编译器自动调用

特征
拷贝构造函数也是特殊的成员函数,其 特征 如下:
  • 1. 拷贝构造函数是构造函数的一个重载形式
  • 2. 拷贝构造函数的参数只有一个必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。
class Date
{
public:

 Date(int year = 1900, 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;
};

int main()
{
     Date d1;
     Date d2(d1);
     return 0;
}

  • 3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
       注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定
义类型是调用其拷贝构造函数完成拷贝的。

class Time
{
public:
 Time()
 {
     _hour = 1;
     _minute = 1;
     _second = 1;
 }

 Time(const Time& t)
 {
     _hour = t._hour;
     _minute = t._minute;
     _second = t._second;
     cout << "Time::Time(const Time&)" << endl;
 }

private:
 int _hour;
 int _minute;
 int _second;
};

class Date
{
private:
 // 基本类型(内置类型)
 int _year = 2023;
 int _month = 1;
 int _day = 1;

 // 自定义类型
 Time _t;
};

int main()
{
 Date d1;
    
    // 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
    // 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构
造函数
     Date d2(d1);
 return 0;
}
4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了 ,还需要自己显式实现吗?
当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?

// 这里会发现下面的程序会崩溃掉。
typedef int DataType;
class Stack
{
public:
 Stack(size_t capacity = 10)
 {
     _array = (DataType*)malloc(capacity * sizeof(DataType));
     if (nullptr == _array)
     {
         perror("malloc申请空间失败");
         return;
     }

     _size = 0;
     _capacity = capacity;
 }

 void Push(const DataType& data)
 {
     // ...
     _array[_size] = data;
     _size++;
 }

 ~Stack()
 {
     free(_array);
 }

private:
 DataType *_array;
 size_t _size;
 size_t _capacity;
};

int main()
{
 Stack s1;
 s1.Push(1);
 s1.Push(2);
 s1.Push(3);
 s1.Push(4);
 Stack s2(s1);
 return 0;
}

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。


5. 赋值运算符重载

       C++ 为了增强代码的可读性引入了运算符重载 运算符重载是具有特殊函数名的函数 ,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
  •      简单来说就是:内置类型可以直接使用运算符运算,因为编译器知道如何运算,而自定义类型无法直接使用运算符,因为编译器不知道如何运算,所以如果要支持自定义类型使用运算符,需要自己实现运算符重载
  • 函数名字为:关键字operator后面接需要重载的运算符符号
  • 函数原型:返回值类型 operator操作符(参数列表)
注意:
  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .*   ::   sizeof   ?:    . 注意以上5个运算符不能重载。

以日期类对象为例:

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

	//私有
    // bool operator==(Date* this, const Date& d2)
    // 这里需要注意的是,左操作数是this,指向调用函数的对象
	bool operator==(const Date& x)
	{
		return _year == x._year
			&& _month == x._month
			&& _day == x._day;
	}

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

//公有
bool operator==(Date x, Date y)
{
	return x._year == y._year
		&& x._month == y._month
		&& x._day == y._day;
}


int main()
{
	Date d1(2023, 9, 1);
	Date d2(2023, 9, 1);

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

	return 0;
}

            -------------------------------------------------------------------------------------------------------------------

依旧以日期类为例:

1.复用逻辑

2.请问下面代码为什么要有返回值?为什么要传引用返回?

返回值是为了支持连续赋值,保持运算符的特性,类似于a = b = c 。d2 = d1 ;   d3 = d2 = d1 ;

传引用返回是因为this指针出函数作用域后会销毁

3.赋值重载与拷贝构造的区别

4.日期类 +  与  +=

5.关于日期类的前置++与后置++ 

日期类案例声明:
#pragma once

#include <iostream>
using namespace std;

class Date
{
	//友元
	friend ostream& operator<<(ostream& out, const Date& d); //流插入

	friend istream& operator>>(istream& in, Date& d);//流提取


public:
	Date(int year = 2023, int month = 1, int day = 1);
	void Print();//打印

	int GetMonthDay(int year, int month) const;//获取每月的天数

	bool operator==(const Date& x) const;
	bool operator!=(const Date& x) const;
	bool operator<(const Date& x) const;
	bool operator<=(const Date& x) const;
	bool operator>(const Date& x) const;
	bool operator>=(const Date& x) const;

	Date& operator+=(int day);
	Date operator+(int day) const;

	//减不仅构成运算符重载,还构成函数重载

	//d1 - 100 日期 - 天数
	Date operator-(int day) const;

	Date& operator-=(int day);
	
	//d1 - d2  日期 - 日期
	int operator-(const Date& d);


	//++d1
	Date& operator++();

	//d1++
	Date operator++(int);

	//--d1   -> d1.operator--();
	Date& operator--();

	//d1--   -> d1.operator--(int);
	Date operator--(int);

	//void operator<<(ostream& out);

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


ostream& operator<<(ostream& out, const Date& d);//流插入

istream& operator>>(istream& in, Date& d);//流提取

日期类案例实现:
#include"Date.h"

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

	if (month == 2 && (((year % 400 == 0) || (year % 4 == 0)) && (year % 100 != 0)))
	{
		return 29;
	}
	else
	{
		return days[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;
	}
	else
	{
		cout << "日期非法" << endl;
	}
}

void Date::Print()
{
	cout << _year << "/" << _month << "/" << _day << endl;
}

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

bool Date::operator!=(const Date& x) const
{
	return !(*this == x);
}

bool Date::operator<(const Date& x) const
{
	if (_year < x._year)
	{
		return true;
	}
	else if (_year == x._year && _month < x._month)
	{
		return true;
	}
	else if (_year == x._year && _month == x._month && _day < x._day)
	{
		return true;
	}
	else
	{
		return false;
	}
}

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

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

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


Date& Date:: operator+=(int day)
{
	if (day < 0)  //day为负数
	{
		*this -= -day;
		return *this;
	}

	_day += day;

	while (_day > GetMonthDay(_year, _month))
	{
		//减去多余的天数
		_day -= GetMonthDay(_year, _month);

		//月进位
		_month++;

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

	return *this;
}

//+ 复用+=
Date Date :: operator+(int day) const
{
	Date tmp(*this);

	tmp += day;

	return tmp;
}

//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)
//		{
//			tmp._month = 1;
//			tmp._year++;
//		}
//	}
//
//	return tmp;
//}


//+= 复用+
//Date& Date::operator+=(int day)
//{
//	*this = *this + day;
//
//	return *this;
//}


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

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


Date& Date::operator-=(int day)
{
	if (day < 0)  //day为负数
	{
		*this += -day;
		return *this;
	}

	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			--_year;
			_month = 12;
		}

		_day += GetMonthDay(_year, _month);
	}

	return *this;
}

Date Date::operator-(int day) const
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}


//--d1 
Date& Date::operator--()
{
	*this -= 1;
	return *this;
}

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

//d1 - d2
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 count = 0;
	while (min != max)
	{
		++min;
		++count;
	}

	return count * flag;
}



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


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


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


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

7. 取地址及 const 取地址操作符重载
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
class A
{
public:
	//const 修饰 *this
	//this指针的类型变成 const A*
	//内部不改变成员变量的成员函数,最好加上const,const对象和普通对象(权限的缩小)都可以调用
	void Print() const
	{
		cout << _a << endl;
	}

	A* operator&()
	{
		return this;
	}

	const A* operator&() const
	{
		return this;
	}

private:
	int _a = 10;
};

void Func(const A& x)
{
	x.Print();

	cout << &x << endl;
}

int main()
{
	A aa;
	aa.Print();

	Func(aa);

	cout << &aa << endl;

	return 0;
}
         这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!


概念性内容均来自比特科技

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

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

相关文章

线性绘制在NSDT 3D场布中的应用

什么是线性摆放&#xff1f; 线性摆放是指将一系列对象按照直线或者曲线进行排列&#xff0c;形成一条线或者弧线状的布局方式。在3D场布中&#xff0c;线性摆放可以应用于多个领域和场景&#xff0c;如展览设计、景观规划、商业空间布置等。 线性绘制在3D场布中的应用 展览设…

Postman全局配置变量token

Postman全局配置变量token 这里主要是介绍在 Postman 中全局配置token&#xff0c;以及方便以后查阅&#xff01;&#xff01;&#xff01; 一、简介 用户在开发或调试网络程序和网页B/S模式的程序时需要一些方法来跟踪网页请求&#xff0c;可使用一些网络的监视工具如Firebu…

多线程详解(下)

文章目录 常见锁策略乐观锁 vs 悲观锁重量级锁 vs 轻量级锁自旋锁 vs 挂起等待锁读写锁可重入锁 vs 不可重入锁公平锁 vs 非公平锁面试相关题 CAS什么是CASCAS 是怎么实现的CAS 有哪些应用1)实现原子类2)实现自旋锁 CAS的ABA问提什么是ABA问提ABA问提引来的BUG解决方法 相关面试…

基于LLMs构建产业多智能体

前言 随着信息技术的发展以及产业数字化的发展&#xff0c;在产业端&#xff0c;信息系统的建设和应用场景的搭建日渐完善&#xff0c;如何从完备的业务系统中挖掘数据价值以及如何从业务互联走向数据驱动决策成为产业数字化的新发展阶段。目前主要由数据中台承担数据汇聚、数…

Kettle安装初始化问题

1、Kettle启动闪退: 原因&#xff1a;自己的JDK是16 8.0的Kettle适配JDK1.8 【Spoon.bat 双击后闪退】解决办法 - 知乎 2、KettleDB连接中文命名 Unexpected problem reading shared objects from XML file : null Error reading information from input stream Invalid …

解读未知--文档图像大模型的探索与应用

前言&#xff1a; 近日&#xff0c;合合信息在多模态大模型与文档图像智能理解专题论坛上进行了分享。多模态大模型指的是能够处理多种语义信息的一种深度学习模型。文档图像智能理解则是指对文档和图像进行智能化解析和理解的技术。合合信息在这个领域的分享&#xff0c;无疑将…

PHP 变动:PHP 8 版本下字符串与数值的弱比较

文章目录 参考环境声明弱比较隐式类型转换字符串连接数学运算布尔判断相等运算符 字符串与数值的弱比较字符串转化为数值的具体规则字符串与数值的弱比较一般情况科学计数法前缀 0E 与 0e PHP8 在字符串与数值的弱比较方面做出的改动数值字符串优化 参考 项目描述搜索引擎Bing…

栈的应用(C++,进制转化、括号匹配)

十进制转化八进制&#xff0c;利用栈 #include<iostream>//十进制转八进制&#xff0c;利用栈 using namespace std; typedef struct stack {int data;stack* next; }stack, * linkstack; void Initstack(linkstack& s) {s NULL; } int Emptystack(linkstack s) {i…

华为云云耀云服务器L实例评测|基于开源库 Stable Diffusion web UI部署AI绘画应用

前言 随着云计算时代的进一步深入&#xff0c;越来越多的中小企业企业与开发者需要一款简单易用、高能高效的云计算基础设施产品来支撑自身业务运营和创新开发。基于这种需求&#xff0c;华为云焕新推出华为云云服务器实例新品。 华为云云服务器具有智能不卡顿、价优随心用、…

整合minio时出现的错误

Action:Correct the classpath of your application so that it contains compatible versions of the classes io.minio.S3Base and okhttp3.RequestBody 这个错误是我在整合minio时报的错&#xff0c;说实话遇到这个错误我还是很头大的&#xff0c;因为之前在springboot项目…

代码随想录算法训练营 动态规划part12

一、最佳买卖股票时机含冷冻期 309. 买卖股票的最佳时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; public class Solution {public int maxProfit(int[] prices) {int len prices.length;if (len < 2) {return 0;}int[] dp new int[3];dp[0] 0;dp[1] -price…

使用Packet Tracer了解网络模型及Lab3 - 1

协议数据单元PDU&#xff08;Protocol Data Unit&#xff09;是指对等层次之间传递的数据单位。协议数据单元(Protocol Data Unit )物理层的 PDU是数据位&#xff08;bit&#xff09;&#xff0c;数据链路层的 PDU是数据帧&#xff08;frame&#xff09;&#xff0c;网络层的PD…

C语言习题

目录 1、数9的个数 2、分数求和 3、求最大值 4、乘法口诀表 4.1、题目内容:在屏幕上输出9*9乘法口诀表 4.2、题目内容:实现一个函数&#xff0c;打印乘法口诀表&#xff0c;口诀表的行数和列数自己指定如:输入9&#xff0c;输出9*9口诀表&#xff0c;输出12&#xff0c;输出12*…

PN结与二极管的特性

PN结的伏安特性 PN结的正向特性 PN结加正向电压时&#xff0c;P区电位高于N区点位&#xff0c;扩散电流大于漂移电流&#xff0c;PN结呈低阻性。 PN结的反向特性 PN结加反向电压时&#xff0c;P区电位低于N区电位&#xff0c;内电场对于扩散运动起到抑制作用&#xff0c;少…

带网络变压器的RJ45网口连接器/集成RJ45网口连接器

​ Hqst华强盛(华轩盛)导读&#xff1a;带网络变压器的RJ45是一种常见的网络连接器&#xff0c;它包含了一个RJ45接口和一个网络变压器&#xff0c;网络变压器位于RJ45接口内部&#xff0c;可以将数据信号转换为适合以太网传输的信号&#xff0c;并具有隔离电路和滤波电…

解决模型半透明时看到内部结构的问题

大家好&#xff0c;我是阿赵。   之前在做钢铁侠线框效果的时候&#xff0c;说到过一种技术&#xff0c;这里单独拿出来再说明一下。   我们经常要做一些模型半透明效果&#xff0c;比如这个钢铁侠的模型&#xff0c;我做了一个Rim边缘光的效果&#xff0c;边缘的地方亮一点…

Python|OpenCV-访问并修改图片像素值,鉴别彩色和灰色图像(6)

前言 本文是该专栏的第6篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在使用OpenCV对图像进行操作的时候,通常需要熟练掌握一些Numpy知识点。因为有的时候需要用到Numpy和OpenCV结合去实现图像的操作,所以说想要写出较好的OpenCV代码的最好方法,就需要有Nump…

【Verilog 教程】5.2Verilog 模块例化

关键字&#xff1a;例化&#xff0c;generate&#xff0c;全加器&#xff0c;层次访问 在一个模块中引用另一个模块&#xff0c;对其端口进行相关连接&#xff0c;叫做模块例化。模块例化建立了描述的层次。信号端口可以通过位置或名称关联&#xff0c;端口连接也必须遵循一些规…

注解,自定义注解

一、什么是注解 二、自定义注解 /*** 自定义注解*/public interface MyAnnotation {String aaa();boolean bbb() default true;String ccc(); }MyAnnotation ( aaa "牛魔王",ccc "sss") public class Test {MyAnnotation ( aaa "aaa",ccc &q…

WAF Bypass及案例实战

文章目录 WAF Bypass1. WAF1.1 WAF 概述1.1.1 常见 WAF1.1.2 WAF 类别1.1.3 WAF 工作原理1.1.4 WAF 的部署方式 1.2 WAF 指纹识别1.2.1 WAF指纹识别工具 1.3 绕WAF的多种方式 2. SQLi Bypass2.1 Bypass 思路2.1.1 层面问题2.1.2 HTTP问题 2.2 绕过分析2.2.1 绕过方式2.2.2 脚本…