C++初阶:类和对象(下)

news2024/9/21 19:09:10

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C++:由浅入深篇

小新的主页:编程版小新-CSDN博客

1.再探构造函数

1.1构造函数体内赋值

之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值。
class Date
{
public:
	//构造函数
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

需要注意的是,上面构造函数的实现是使每个成员变量都有了一个初始值,但是构造函数体的语句其实只能被认为是赋值,而不是初始化,因为初始化只能初始化一次,而赋值可以有多次。

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

1.2初始化列表

构造函数初始化还有一种方式,就是初始化列表。

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式

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

1.3小细节

一:每个成员变量在初始化列表中只能出现一次
语法理解上初始化列表可以认为是每个成员变量定义初始化的地方,初始化只能初始一次。
二:下面几个成员变量,必须在初始化列表初始化
1.const成员变量
const变量必须在定义的时候初始化,并且只有这一次初始化机会。而初始化列表就是成员变量定义初始化的地方,所以const成员变量必须在初始化列表初始化。
初始化:
class Date
{
public:
	
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
		, _a(1)
	{}
private:
	int _year;
	int _month;
	int _day;
	const int _a;
};

2.引用成员变量

引用必须初始化,在定义时就要给一个初始值,而初始化列表是每个成员变量定义初始化的地方,所以引用成员变量必须在初始化列表初始化。

初始化:

class Date
{
public:
	
	Date(int& xx,int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
		, _a(1)
		, _ra(xx)
	{}
private:
	int _year;
	int _month;
	int _day;
	const int _a;
	int& _ra;
};

3.自定义类型成员

若一个类没有默认构造函数,那我们在实例化类类型对象时就要传参对其初始化,所以没有默认构造的类类型变量,必须放在初始化列表位置就要初始化,否则会编译报错。

初始化:
 class Time
{
public:
	Time(int hour)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};

class Date
{
public:
	Date(int& xx,int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
		, _a(1)
		, _ra(xx)
		,_t(1)
	{}
private:
	int _year;
	int _month;
	int _day;
	const int _a;
	int& _ra;
	Time _t;

};

总结:在定义时就必须要初始化的变量类型,必须在初始化列表初始化。

三:C++11支持持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使用的。
如果这个成员在声明位置给了缺省值,初始化列表会用这个缺省值初始化。如果你没有给缺省值:
内置类型:否初始化取决于编译器,C++并没有规定。
自定义类型:调用这个成员类型的默认构造函数,如果没有默认构造会编译错误。
下面是给了缺省值的情况:
#include<iostream>
using namespace std;

class Time
{
public:
	Time(int hour)
		:_hour(hour)
	{
	cout << "Time()" << endl;
	}
private:
	int _hour;
};
class Date
{
public:
	Date()
		:_month(2)
	{
		cout << "Date()" << endl;
	}
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	// 注意这里不是初始化,这里给的是缺省值,这个缺省值是给初始化列表的
	// 如果初始化列表没有显示初始化,默认就会用这个缺省值初始化
	int _year = 1;
	int _month = 1;
	int _day;
	Time _t = 1;
	const int _n = 1;
	int* _ptr = (int*)malloc(12);
};

四:尽量使用初始化列表初始化

因为初始化列表实际上就是当你实例化一个对象时,该对象的成员变量定义初始化的地方,所以 无论你是否使用初始化列表对成员变量初始化,都会走初始化列表
对于内置类型,使用初始化列表或者构造函数体内赋值进行初始化时没有什么差别的。
对于自定义类型可以提高代码效率。
class Time
{
public:
	Time(int hour = 0)
	{
		_hour = hour;
	}
private:
	int _hour;
};

class Date
{
public:
	// 使用初始化列表
	Date(int hour)
		:_t(12)// 调用一次Time类的构造函数
	{}
private:
	Time _t;
};

对于以上代码,当我们要实例化一个Date类的对象时,由于使用初始化列表进行初始化,在实例化过程中只调用了一次Time类的构造函数。
如果我们不使用初始化列表,使用构造函数体内赋值的话:

class Time
{
public:
	Time(int hour = 0)
	{
		_hour = hour;
	}
private:
	int _hour;
};
class Date
{
public:
	// 构造函数体内赋值
	Date(int hour)
	{ 
		Time t(hour);// 调用一次Time类的构造函数
		_t = t;// 调用一次Time类的赋值运算符重载函数
              //在此之前其实还会调用一次构造函数,因为_t是一个新的Time对象,它需要进行初始化
	}
private:
	Time _t;
};

这时,我们要实例化一个Datet类的对象时,在实例化Date对象时调用一次Time类的构造函数,然后还需要调用了一次Time类的赋值运算符重载函数,这样效率就降下来了。

五.成员变量在类中的声明顺序就是初始化列表初始化的顺序
初始化顺序跟成员在初始化列表出现的的先后顺序无关,建议声明顺序和初始化列表顺序保持⼀致。
下面我们看一道练习:
A. 输出 1 1
B. 输出 2 2
C. 编译报错
D. 输出 1 随机值
E. 输出 1 2
F. 输出 2 1
//下面程序的运行结果是什么
#include<iostream>
using namespace std;
class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}
	void Print() 
	{
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2 = 2;
	int _a1 = 2;
};
int main()
{
	A aa(1);
	aa.Print();
}

已知成员变量在类中的声明顺序就是初始化列表初始化的顺序。先声明的_a2,所以先初始化_a2,由于_a2是用_a1进行初始化的,而_a1还未被初始化,是个随机值,所以_a2最后是个随机值。后声明的_a1,然后在初始化_a1是1。这是虽然_a1是1了,但是_a2不会变成1,因为只能初始化一次,所以答案故选D。

2.隐式类型转换

我们在学习C语言时就知道,如果赋值两边的类型不同时就可能发生隐式类型转换。

隐式类型转换转换是由编译器自动进行的,无需程序员明确指定。

显示类型转换则是由程序员通过特定的语法明确指示编译器进行类型转换。

2.1内置类型

在发生隐式类型转换时,如果两边都是内置类型会生成一个临时变量(类型转换会生成临时变量)。将右操作数强制类型转换为左操作数的类型,最后用这个临时变量给左操作数赋值。临时变量具有常性,不能更改

int main()
{
	double j = 1.1;
	int i = j;//隐式类型转换
	int& a = j;//error  权限放大
	const int& b = j;//正确 权限平移
	return 0;
}

 通过引用来测试,我们得知a,b,j指向同一块空间。a,b都是j的别名,然而只用常引用是可行的,这也验证了发生类型转换时产生的临时变量具有常性。

2.2自定义类型

在发生隐士类型转换时,如果将一个内置赋值给自定义类型,编译器产生一个自定义类型的临时变量,然后会调用这个自定义类型的构造函数初始化这个临时变量,最后用这个临时变量对左操作数进行拷贝构造。临时变量也具有常性,不可修改。

#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1, 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;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1 = 2024;//发生隐式类型转换
	Date d2 = { 2024,8 };

	d1.Print();
	d2.Print();
	return 0;
}

2.3explicit关键字 

C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数、 但当构造函数前面加explicit就不再支持隐式类型转换。
#include<iostream>
using namespace std;

class A
{
public:
	// 构造函数explicit就不再支持隐式类型转换
	 explicit A(int a1)
		//A(int a1)
		:_a1(a1)
	{}
	explicit A(int a1, int a2)
	//A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}
	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a1 = 1;
	int _a2 = 2;
};
int main()
{
	// 1构造一个A的临时对象,再用这个临时对象拷⻉构造aa1
	// 编译器遇到连续构造+拷⻉构造->优化为直接构造
	A aa1 = 1;
	aa1.Print();
	const A& aa2 = 1;
	// C++11之后才支持多参数转化
	A aa3 = { 2,9 };
	aa3.Print();
	return 0;
}

3.static成员

3.1定义

用static修饰的成员变量,称之为静态成员变量,用static修饰的成员函数,称之为静态成员函数

class A
{
public:
    static int Print()//静态成员函数
	{
		cout << "Print()" << endl;
	}
private:
	static int _a;//静态成员变量
};

3.2小细节

1.静态成员变量一定要在类外进行定义初始化,定义时不添加static关键字。
class A
{
public:
	static int Print()//静态成员函数
	{
		cout << "Print()" << endl;
	}
private:
	static int _a;//静态成员变量
};

int A::_a = 1;

这里静态成员变量_a虽然是私有,但是我们在类外突破类域直接对其进行了访问。这是一个特例,不受访问限定符的限制,否则就没办法对静态成员变量进行定义和初始化了。

2.静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
class A
{
public:
	static int Print()//静态成员函数
	{
		cout << "Print()" << endl;
	}
private:
	static int _a;//静态成员变量
};

int A::_a = 1;

int main()
{
	cout << sizeof(A) << endl;
	return 0;
}

最终计算的结果是1,因为静态成员_a存在静态区,属于整个类,也属于类的所有对象。所以在计算类的大小或则类对象的大小时,静态成员的大小并不算在其中。

3.静态成员函数没有this指针,可以访问其他的静态成员,但是不能访问非静态的。
class Test
{
public:
	static void Fun()
	{
		cout << _a << endl; //error不能访问非静态成员
		cout << _n << endl; //正确
	}
private:
	int _a; //非静态成员
	static int _n; //静态成员
};

注意:非静态的成员函数,可以访问任意的静态成员变量和静态成员函数。
4.静态成员也是类的成员,受public、protected、private 访问限定符的限制。
所以当静态成员变量设置为private时,尽管我们突破了类域,也不能对其进行直接访问。
5.突破类域就可以访问静态成员,可以通过类名::静态成员 或者 对象.静态成员 来访问静态成员变量和静态成员函数。
1.当静态成员成员变量设置为公有时:
class Test
{
public:
	static int _n; 
};

int Test::_n = 0;

int main()
{
	Test test;
	cout << test._n << endl; //1.通过类对象突破类域进行访问
	cout << Test::_n << endl; //2.通过类名突破类域进行访问
	return 0;
}

2.当静态成员变量被设置为私有时:

class Test
{
public:
	static int GetN()
	{
		return _n;
	}
private:
	static int _n;
};

int Test::_n = 0;

int main()
{
	Test test;
	cout << test.GetN() << endl; //1.通过对象调用成员函数进行访问
	cout << Test::GetN() << endl; //2.通过类名调用静态成员函数进行访问
	return 0;
}

6.静态成员变量不能在声明位置给缺省值初始化,因为缺省值是给构造函数初始化列表用的,静态成员变量不属于某个对象,不走构造函数初始化列表。

4.友元

友元提供了一种突破类访问限定符封装的方式,友元分为:友元函数和友元类。

在函数声明或者类声明的前面加friend,并且把友元声明放到一个类的里面。

4.1友元函数 

我们有时想在类外面访问类的私有或保护成员,但是碍于访问限定符的限制,我们不能直接访问。如果一定要访问的话,我们就可以借助友元函数。

它的用法:friend+函数的声明

class Date
{
public:
	friend void Print(const Date& d);
	Date(int year = 1, 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;
};
void Print(const Date& d)
{
	cout <<d._year<< "-" << d._month << "-" <<d. _day << endl;
}
注意:
友元函数仅仅是一种声明,他不是类的成员函数。
友元函数可以在类定义的任何地声方明,不受类访问限定符限制。
一个函数可以是多个类的友元函数。
友元函数不能被const修饰。
友元函数的调用和普通函数的调用原理相同。

4.2友元类

友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有和保护成员。

友元类的用法:friend+class+类名

#include<iostream>
using namespace std;
class A
{
	// 友元声明
	friend class B;//B类是A类的友元
private:
	int _a1 = 1;
	int _a2 = 2;
};

class B
{
public:
	void func1(const A& aa)
	{
		cout << aa._a1 << endl;
		cout << _b1 << endl;
	}
	void func2(const A& aa)
	{
		cout << aa._a2 << endl;
		cout << _b2 << endl;
	}
private:
	int _b1 = 3;
	int _b2 = 4;
};
int main()
{
	A aa;
	B bb;
	bb.func1(aa);
	bb.func2(aa);
	return 0;
}
注意:
1.友元类的关系是单向的,不具有交换性。
比如上面的代码B类是A类的友元,B类可以访问A类中的成员变量和成员函数,但是A类不是B类的友元,A就不能随意访问B类。
2.友元类关系不能传递
如果A类是B类的友元, B类是C类的友元,但是A类不是C类的友元。
3.有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

5.内部类 

5.1定义

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。
内部类是一个独立的类,不属于内部类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以不能用外部类的对象去访问内部类的成员,外部类定义的对象中不包含内部类,并且 内部类默认是外部类的友元类。
class A
{
public:
	class B//B类是A类的友元
	{
	private:
		int _j;
	};
private:
	int _a;
	int _b;
};

5.2小细节 

1.内部类定义在外部类的public、protected、private都是可以的。

当A类跟B类紧密关联,如果放到private/protected位置,那么A类就是B类的专属内部类,其
他地方都用不了。
2.注意内部类可以直接访问外部类中的static成员,不需要外部类的对象 / 类名。
include<iostream>
using namespace std;
class A
{
private:
	static int _k;
	int _h = 1;
public:
	class B // B默认就是A的友元
	{
	public:
			void foo(const A & a)
		{
			cout << _k << endl; //OK 直接访问static成员
			cout << a._h << endl; //OK
		}
	};
};

//static成员在外部定义初始化
int A::_k = 1;

int main()
{
	//B是一个独立的类,只是外部类类域的限制
	A::B b;
	A aa;
	b.foo(aa);
	return 0;
}

3.外部类的大小和内部类没有关系。

class A
{
private:
	int _n;
	int _m;
public:
	class B // B是A的友元
	{
	public:
		int _a;
	};
};
int main()
{
	A a;
	cout << sizeof(a) << endl;
	return 0;
}

 6.匿名对象

用类型(实参) 定义出来的对象叫做匿名对象,想必之前我们定义的 类型 对象名(实参) 定义出来的叫有名对象。
匿名对象⽣命周期只在当前一行,一般临时定义一个对象当前一下下即可,就可以定义匿名对象。
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		cout << "Date" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		cout << "Date(const Date& d)" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "~Date()" << endl;
		_year = _month = _day = 0;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date();//匿名对象
	return 0;
}

 要延长匿名对象的生命周期,一种常见的方法是将其绑定在引用上。

int main()
{
	const Date& dc = Date();//匿名对象也具有常性
	return 0;
}

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

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

相关文章

Parsing error: The keyword ‘interface‘ is reserved配置优化

当我们在创建Vue项目时,Vue默认是配置了eslint代码规范检查的,不过我们在项目中Typescript来编写代码时,却报了标题的错误,对应的代码如下: <script lang="ts"> export default{name: "DlHeader" } </script><script setup lang=&quo…

利用OpenCvSharp进行图像相关操作

前言 程序设计过程&#xff0c;有时也需要对图像进行一些简单操作&#xff0c;C#没有现成的图像处理库&#xff0c;但有人对OpenCV进行了包装&#xff0c;我们可以很方便的使用OpenCvSharp对图像进行操作。当然了&#xff0c;这也需要使用的人员进行一些研究&#xff0c;但相对…

【C语言篇】猜数字游戏(赋源码)

文章目录 猜数字游戏前言随机数生成randsrandtime设置随机数生成范围 猜数字游戏的实现 猜数字游戏 前言 在前两篇博客对于分支和循环语句进行了详细的介绍&#xff1a; 分支语句详解 循环语句详解 我们就可以写一写稍微有趣的代码了&#xff0c;比如&#xff1a; 写一个…

用uniapp 及socket.io做一个简单聊天app 撤回聊天及保留聊天记录 6

撤回的设计 通过聊天&#xff0c;发送一个信息&#xff0c;界面自动将信息撤回&#xff0c; 当时要有时间的限制。同时也要将撤回记录到数据库中。async sendMessage(message, type text) {this.$refs.popup.close();const messageData {sn: uuidv4(),group_name: this.gro…

【MySQL】MySQL9.0发布,有点小失望

前言 &#x1f34a;缘由 MySQL一更新&#xff0c;实在有点闹心 &#x1f3c0;事情起因&#xff1a; 大家好&#xff0c;我是JavaDog程序狗 今天跟大家聊一下MySQL9.0新版本发布&#xff0c;仅代表个人观点&#xff0c;大佬DBA轻喷 &#x1f4d8;『你想听的故事 』 本狗在…

【python】Python中实现定时任务常见的几种方式原理分析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

安全主机软件是如何有效应对暴力破解的?

在网络安全日益严峻的今天&#xff0c;暴力破解作为一种常见的攻击手段&#xff0c;时刻威胁着企业和个人的账户安全。为了有效抵御这一威胁&#xff0c;主机安全作为一款集实时监测、智能分析、风险预警于一体的主机安全软件&#xff0c;通过多维度、智能化的防护策略&#xf…

便携式气象监测系统的功能与应用

在科技日新月异的今天&#xff0c;气象监测作为农业生产、城市规划、环境保护及灾害预防等领域不可或缺的一环&#xff0c;正经历着前所未有的变革。其中&#xff0c;便携式气象监测系统的出现&#xff0c;如同一股清新的风&#xff0c;吹散了传统气象观测的种种限制&#xff0…

3.达梦数据库基础运维管理

文章目录 前言一、基础数据库管理权限角色管理1.1 DM 系统管理员的类型1.2 角色责则分类 DM 数据库2.1 数据库评估2.2 状态和模式 参考内容 前言 本篇博客为上一篇博客的进阶版&#xff0c;主要针对常规达梦数据库的基本管理上面 一、基础数据库管理 权限角色管理 1.1 DM 系…

【Git企业级开发实战指南②】分支管理、远程操作

目录 一、分支管理1.1理解分支1.2创建分支1.3切换分支1.4合并分支1.5删除分支1.6合并冲突1.7 分支管理策略1.7.1分支策略 1.8bug分支1.9删除临时分支 二、远程操作2.1理解分布式版本控制系统2.2 远程仓库2.2.1 新建远程仓库2.2.2 克隆远程仓库2.2.3向远端仓库推送2.2.4拉取远端…

ROS2 Humble 学习【openEuler】

ROS2 Humble 学习 1 介绍1.1 概述1.2 ROS2 详细介绍1.3 openEuler 安装 ROS2 Humble1.4 ROS2 系统架构 2 ROS2 基础2.1 节点编写、编译、运行【简单示例】节点编写节点编译 g节点运行节点编译 make节点编译 CMakeLists.txtCMake依赖查找流程Python 依赖查找流程 2.2 节点交互、…

MySQL深分页和浅分页

前言 最近有面试过也遇到了问关于深分页问题&#xff0c;在这里简单从MySQL、ES等方面分享一下自己对该问题认识和总结。 一、深分页定义 可以从ES定义上来划分浅分页和深分页的边界&#xff0c;即页数超过10000页为深分页&#xff0c;少于10000页为浅分页。 二、MySQL深分…

数字化时代:蚓链助力企业破局与腾飞!

在当今数字化浪潮汹涌澎湃的时代&#xff0c;企业面临着前新机遇与新挑战。您是否渴望在竞争激烈的市场中实现数字化弯道超车&#xff1f;是否梦想着打造专属自己的独特生意赛道&#xff1f;是否期盼着拥有专享的资源生态圈&#xff1f;如果您的答案是肯定的&#xff0c;那么蚓…

CSP - J day9

一. 题目 &#xff08;1&#xff09;早安 思路&#xff1a; &#xff08;1&#xff09;cin和scanf读入字符串时遇到空格或换行就停止读入&#xff0c;对于要读入带空格的字符串时&#xff0c;常用 两种方法&#xff1a; // 法一string s;getline( cin, s ); // 法…

OrangePi AIpro学习1 —— 烧写和ssh系统

目录 一、下载烧写工具和系统 二、烧写和启动 2.1 烧写和启动 2.2 烧写失败后的问题解决 三、串口连接到主机 3.1 串口连接到主机 四、网络连接到主机 4.1 修改香橙派IP地址 4.2 win11配置以太网静态ip 4.4 主机和香橙派直连 4.5 主机和香橙派连接到同一个路由器 五…

Hive SQL进阶:掌握间隔连续查询技巧,优化大数据分析(二)

目录 1.访问次数最多的5个用户 2.近 30 天的每日活跃用户数 3.获取1-180天注册活跃留存表 4.学生名次统计 5.最近连续3周连续活跃用户数 6.最近7天内连续3天活跃用户数 7.餐馆营业额变化增长 相关拓展 1.访问次数最多的5个用户 输出每个app 下访问次数最多的5个用户 返…

DC-7靶机渗透测试

DC-7靶机 DC: 7 ~ VulnHub 文章目录 DC-7靶机信息收集web渗透权限提升Drupal后台getshell权限提升靶机总结信息收集 经过扫描得到IP地址为192.168.78.154.其中开启了ssh和80端口,看来立足点就在于web渗透找到漏洞,获取用户密码来进行ssh连接进行寻找提权方案了使用dirb扫描…

Windows平台下内存泄漏检测工具Visual Leak detector介绍(vscode使用)

!!!此工具只能检测配合VC进行代码的内存泄漏检测 1、搜索VLD工具下载 2、配置环境变量 3、在main.cpp中加入#include<vld.h> 4、在CMakeLists.txt中添加 SET(VLD_PATH "xxx") # 链接vld静态库 target_link_libraries(${PROJECT_NAME} PRIVATE ${VLD_PATH})…

学习STM32(2)--STM32单片机GPIO应用

目录 1 引 言 2 实验目的 3 实验内容 3.1掌握STM32F103的GPIO控制 3.1.1 GPIO的分组 3.1.2 GPIO的常用功能 3.1.3 STM32单片机GPIO位结构 3.1.4 STM32单片机GPIO工作模式 3.1.5 STM32的GPIO 输出-点亮LED编程要点 使用GPIO时&#xff0c;按下面步骤进行&#xff1…

antd-5版本table组件修改滚动条样式不生效问题

问题描述 在react项目中使用antd-ProComponents组件库的Protable组件时修改table自带的滚动条样式不生效。 排查记录 一般来说直接table组件库要自定义滚动条的样式&#xff0c;只需要修改 ant-table-body 的样式即可&#xff0c;代码如下&#xff1a; .ant-table-body {&am…