C++类和对象下

news2025/1/11 6:34:48

专栏:C/C++
个人主页:HaiFan.
专栏简介:本章为大家带来C++类和对象相关内容。

类和对象下

  • 类的默认成员函数
    • 构造函数
    • 析构函数
    • 拷贝构造函数
    • 运算符重载
  • const成员
  • 再谈构造函数
    • 构造函数体赋值
    • 初始值列表
  • explicit关键字
  • static成员
  • 友元
  • 内部类
  • 匿名对象
  • 拷贝对象时一些编译器优化

类的默认成员函数

默认成员函数是指在定义类时如果没有显式声明该成员函数,编译器会自动生成默认实现的成员函数。

构造函数

构造函数是一种特殊的成员函数,它没有返回值。它的作用是在创建对象的时候初始化成员变量,如果没有显示的定义构造函数,编译器会隐式的生成一个默认构造函数。如果定义了构造函数。默认的就不会在自动生成。

特点:

  • 函数名与类名相同
  • 没有返回值
  • 创建对象的过程中编译器自动调用对应的构造函数
  • 可以重载
  • 在对象整个生命周期中只调用一次
class Date
{

public:

	Date()
	{
		//无参构造函数
	}

	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
        //带参构造函数
	}

	void GetDate()
	{
		cout << _year << ':' << _month << ':' << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date one;//调用无参
	one.GetDate();
	Date two(2023, 5, 6);//调用有参
	two.GetDate();
    
    //如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
	return 0;
}

输出结果 -858993460:-858993460:-858993460 2023:5:6


第一个结果是个随机值,为什么呢?构造函数不是会初始化吗?

当类中没有定义构造函数或者定义了构造函数但没有对成员变量进行初始化的时候,前者编译器会自动生成默认构造函数,但是这个构造函数不会对类中的内置类型进行初始化,依旧是随机值。如果是自定义类型,默认生成的构造函数会进行初始化,前提是自定义类型中定义了构造函数。

#include <iostream>

using namespace std;

class Stack
{
private:
	int* _a;
	int _capacity;
	int _t;

public:
	Stack(int capacity = 4)
	{
		_a = new int[capacity];
		_capacity = capacity;
		_t = -1;
	}

	void push(int x)
	{
		_a[++_t] = x;
	}

	int top()
	{
		return _a[_t];
	}
};

class MyQueue
{
private:
	Stack q1;
	Stack q2;
};

int main()
{
	MyQueue a1;
	return 0;
}

上面的代码中,MyQueue中没有构造函数,但是编译器会自动生成从而完成初始化。

在这里插入图片描述

如果把Stack类中的构造函数给注释了,q1和q2还是会出现随机值。


C++11中针对内置类型给成员不初始化的缺点,打了补丁。

内置类型的成员变量在类中声明时可以给定默认值,如果创建该类的对象时没有提供该成员变量的值,则该成员变量将被初始化为默认值。

#include <iostream>

using namespace std;

class Date
{

public:

	//Date()
	//{
	//	
	//}

	//Date(int year, int month, int day)
	//{
	//	_year = year;
	//	_month = month;
	//	_day = day;
	//}

	void GetDate()
	{
		cout << _year << ':' << _month << ':' << _day << endl;
	}
private:
	int _year = 2023;
	int _month = 05;
	int _day = 06;
};

int main()
{
	Date one;
	one.GetDate();
	return 0;
}

输出结果 2023:5:6

注:需要注意的是,只有在声明类的同时给成员变量赋予初始值,它们才会被初始化。如果你使用了构造函数来初始化内置类型的成员变量,则默认值将不起作用。


无参的构造函数和全缺省的构造函数都称为默认构造函数,并且构造函数只能有一个,如果同时出现,会出现 重载不明确的报错

析构函数

析构函数是在对象被销毁时(生命周期结束时)自动调用。与构造函数不同,析构函数没有任何参数,没有返回值,其名称由类名前加上 ~ 组成。

主要作用:

用于清理和释放对象占用的资源,如动态内存开辟的空间,打开的文件等,如果忘记释放的话,会造成内存泄露等问题。

一个类只能有一个析构函数,若未显示定义,系统会自动生成默认的析构函数

析构函数不能重载

内置成员类型,销毁时不需要资源清理,最后系统直接将其内存回收即可

class Data
{
private:
	int _day;
	int _month;
	int _year;

public:

	Data(int day, int month, int year)
	{

		cout << "--------Data--------" << endl;
		_day = day;
		_month = month;
		_year = year;
	}

	~Data()
	{
		cout << "--------~Data-------" << endl;
	}
};

int main()
{
	Data a(8, 5, 2023);

	return 0;
}

输出结果--------Data-------- --------~Data-------


如果是自定义类型

class Time
{
private:
	int _a;

public:
	~Time()
	{
		cout << "--------~Time-------" << endl;

	}
};

class Data
{
private:
	int _day;
	int _month;
	int _year;
	
public:

	Time _t;
};

int main()
{
	Data a;

	return 0;
}

a销毁时,要将其内部包含的Time类的 _t对象给销毁,所以会调用Time类的析构函数,但是main函数中是不能直接调用Time类中的析构函数的,编译器会调用Data类的析构函数,因为没有写,会自动给Data类生成一个默认的析构函数,然后在其内部调用Time。


如果类中没有申请资源,析构函数可以不屑,直接使用编译器生成的默认析构函数就行。

拷贝构造函数

拷贝构造函数用于将一个对象复制到另一个对象中,拷贝构造函数只有一个参数,通常是一个引用类型的对象,这个参数指定了需要被复制的对象。这个函数不需要自己去调用,在复制对象的过程中编译器会自动调用。

	className(const className& other)
	{
		//拷贝内容
	}

拷贝构造函数的参数是一个常量引用,这个引用指向需要复制的对象。如果使用传值的方式,编译器会直接报错。(首先在C++中,内置类型的传参是直接赋值,而自定义类型的传参则是会进去类中的拷贝构造函数进行一个拷贝,如果拷贝构造函数中是用的传值,就会造成无限递归)

class Date
{
private:
	int _year;
	int _day;
	int _month;

public:

	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	//Date(Date other)错误写法
	Date(const Date& other)
	{
		_year = other._year;
		_month = other._month;
		_day = other._day;
	}
};

int main()
{
	Date d(2023,5,9);
	Date d1(d);

	return 0;
}

若没有显示定义,则编译器会生成默认的拷贝构造函数,默认的拷贝构造函数是按照字节完成拷贝的,这种拷贝叫做浅拷贝,或者值拷贝。

class Date
{
private:
	int _year;
	int _day;
	int _month;

public:

	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
};

int main()
{
	Date d(2023, 5, 9);
	Date d1(d);

	return 0;
}

在这里插入图片描述

在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。


像上面的代码,全都是内置类型的,不需要自己去实现拷贝构造函数,如果是有动态内存的,资源申请之类的,则需要自己写拷贝构造函数。

class Stack
{
private:
	int* _a;
	int t;
	int _capacity;

public:
	Stack(int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (nullptr == _a)
		{
			perror("malloc fail");
			exit(-1);
		}

		_capacity = capacity;
		t = -1;
	}

	void push(int x)
	{
		_a[++t] = x;
	}

	int top()
	{
		return _a[t];
	}

	~Stack()
	{
		free(_a);
		_a = nullptr;
	}
};

int main()
{
	Stack stk1;
	Stack stk2(stk1);

	return 0;
}

在这里插入图片描述

这个代码就是一个错误的示范,因为Stack类涉及到了动态内存分配,并且类中并没有显式定义拷贝构造函数,这个时候编译器会自定生成一个默认的拷贝构造函数,编译器生成的这个,是浅拷贝。

在这里插入图片描述

通过监视,可以发现,stk1和stk2的栈数组指向的是同一块空间,所以在释放资源的时候,当其中一个先释放之后,另一个在释放,就会造成错误,同一块空间不能连续释放两次。

运算符重载

这里先写了一个日期类

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

	Date(const Date& other);

private:
	int _year;
	int _day;
	int _month;


};

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


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

int main()
{
	Date d(2023, 5, 9);
	Date d1(2024, 5, 9);

	cout << (d1 > d) << endl;

	return 0;
}

实现一个日期类,很简单,如果让实现一个比较日期大小的函数呢?

bool Greater(const Date& d, const Date& d1)
{
	if (d._year > d1._year)
	{
		return true;
	}
	else if (d._year == d1._year && d._month > d1._month)
	{
		return true;
	}
	else if (d._year == d1._year && d._month == d1._month && d._day > d1._day)
	{
		return true;
	}

	return false;
}

也很简单,但是要把类中的私有属性给换成公共的。

但是在调用函数的时候是 cout << Greater(d1, d) << endl;这样调用的,
没有 d1 > d这样看着直观。

为了增江代码的可读性,C++引入了运算符重载。运算符重载是指为自定义的数据类型,实现对已有运算符的重定义和扩展,使得程序能够像操作内置类型数据那样进行操作。

函数名:关键字operator后面跟需要重载的运算符符号
函数原型:返回值类型operator操作符(参数列表)

注:

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

比如上面的代码,现在把它以运算符重载的方式实现

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

	Date(const Date& other);


	bool operator> (const Date& d1)
	{
		if (_year > d1._year)
		{
			return true;
		}
		else if (_year == d1._year && _month > d1._month)
		{
			return true;
		}
		else if (_year == d1._year && _month == d1._month && _day > d1._day)
		{
			return true;
		}

		return false;
	}

private:
	int _year;
	int _day;
	int _month;


};

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


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

int main()
{
	Date d(2023, 5, 9);
	Date d1(2024, 5, 9);
	
	cout << (d1 > d) << endl;

	return 0;
}

这样,就可以直接使用>号来直接比较大小了。

同样的,日期+日期,减日期,都可以利用运算符重载来实现


当我们输出日期的时候,是调用的Date类中的Print函数,而自定义类型则可以使用cout,那么通过重载,自定义类型可以使用吗?

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

	void Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}
	ostream& operator<< (ostream& out)
	{
		 out << _year << "年" << _month << "月" << _day << "日" << endl;
        return out;
	}
private:
	int _year;
	int _day;
	int _month;
};

int main()
{
	Date d(2023, 5, 13);
	//d.Print();
	d << cout;//出现这种情况是因为在调用这个重载的时候,是先传的this指针,d.operator<<(cout)跟这个形式等价
	return 0;
}

上面的代码虽然也可以利用<<来实现输出,但是却是对象在前,那么怎么弄,可以把这个d << cout颠倒一下?

在类外重载就可以了。

在类外重载还面临一个问题----类外无法访问到类的私有属性,这个时候可以使用友元(指的是某个类或函数被允许访问另一个类中的私有成员)。

class Date
{

	friend ostream& operator<< (ostream& out, const Date& other);
	friend istream& operator>> (istream& in,Date& other);
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 _day;
	int _month;
};
//<<中的other为什么带const而>>中的却不带,前者是输出,输出不需要改变原对象中的内容,故加const,而后者是输入,需要改变原对象的内容,所以不带const
ostream& operator<< (ostream& out,const Date& other)
{
	 out << other._year << "年" << other._month << "月" << other._day << "日" << endl;
	 return out;
}

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

现在,就能对自定义类型的数据进行cin和cout操作了。

const成员

const成员是在类的定义中通过在函数声明后添加const关键字来指定的。const成员函数可以让我们确保该成员函数不会修改类的成员变量。

在类外部定义const成员函数时,需要在函数声明和函数定义中都加上const关键字。

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

	void Print()const
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}

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

就比如这个,就可以在Print后面加上const,因为这个函数不会对对象做出任何改变。


再谈构造函数

构造函数体赋值

对象实例化的过程中,编译器会调用构造函数,来给成员变量一个值。

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

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

其实上面的代码,并不能被称之为初始化,称之为赋值更合适,因为初始化只能初始化一次,而赋值可以进行多次。

初始值列表

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

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

上面的代码中出现了新的东西,如冒号和花括号之间的代码。其中花括号定义了(空的)函数体。我们把新出现的部分叫做构造函数初始值列表,它负责新创建的对象的一个或者几个数据成员赋初值。构造函数初始值是成员名字的一个列表,每个名字后面紧跟括号括起来(或者在花括号内的)成员初始值。不同成员的初始化通过逗号分隔开来。


有时候我们可以忽略初始化和赋值的差异,但也有其他情况是我们不能忽略的,如果成员是引用类型或者const类型的话,我们就不能为其赋值,只能选择用初始值列表来实现。

class A
{
	A(int a,int b)
		:_a(a)
		,_b(b)
	{}

private:
	const int _a;
	int& _b;
};

注:

每个成员变量只能在初始化列表中出现一次
类中包含一下成员,必须放在初始化列表位置进行初始化
引用成员变量
const成员变量
自定义类型成员(且该类没有默认构造函数)

尽量使用初始值列表,因为不管你是否使用初始值列表,对于自定义类型的成员变量,一定会先使用初始化列表

还有一点呢值得注意

成员在类中的声明次序就是其在初始化了i二标中的初始化顺序,与其在初始化列表中的先后顺序无关。

class Stack
{
public:
	Stack(int capacity = 10)
		:_capacity(capacity)
		,_t(-1)
		,_a((int*)malloc(sizeof(int)* _capacity))
	{
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
	}

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

像上面的代码,初始值列表中先写的capacity,后是栈数组的初始化,但是初始化顺序不是这样的,是先给栈数组初始化,然后是_t,最后是 _capacity,所以这里给栈数组开空间中的操作是错误的。

explicit关键字

隐式类型转换相信大家都不陌生,那么自定义类型也可以隐式类型转换吗?

class A
{
public:
	A(int x)
		:_a(x)
	{}

	void Print()
	{
		cout << _a << endl;
	}

private:
	int _a;
};

int main()
{
	A cc(2);
	cc.Print();
	A bb = 2;
	bb.Print();
	return 0;
}

这个代码会输出2 2

A cc(2)使用了显示构造函数进行对象实例化,但是A bb = 2,则使用了隐式类型转换,其实本质上是调用了构造函数A(int),将整型2转换成A类型的临时对象,然后借助临时对象调用拷贝构造函数将其赋值给了bb对象


如果不想让这个程序可以隐式类型转换,可以通过将构造函数声明为explicit加以阻止。

在这里插入图片描述

explicit关键字只对一个实参的构造函数有效,需要多个实参的构造函数不能用于隐式类型转换,所以无需将这些构造函数指定为explicit关键字。

只能在类内部声明构造函数的时候使用该关键字,在类外部定义时不应重复

static成员

在类中,是否存在一种成员,与对象无关,只与类有关呢?C++给出了答案:有的,声明为 static的类成员称类的静态成员,用static修饰的成员变量,称之为静态成员变量,用static修饰的成员函数,称之为静态成员函数

class A
{
public:
	A(int a)
		:_a(a)
	{}

	void ThisSum()
	{
		sum += _a;
	}

	static int GetSum();

private:
	int _a;
	static int sum;
};

int A::sum = 0;

int A::GetSum()
{
	return A::sum;
}

int main()
{
	A a(1);
	A b(1);
	b.ThisSum();
	a.ThisSum();
	cout << A::GetSum() << endl;
	return 0;
}

上面的代码中会输出 2 ,A类中声明了一个静态成员函数和一个静态成员变量(一般会在类中声明,在类外定义,定义的时候就不需要再重复写static了。通过类名::静态成员或者对象.静态成员可以访问到),然后进行了两次ThisSum的操作,可以看出,静态成员变量/函数都属于整个类,而不是单个对象,因此程序在运行的时候,对象创建了两次,而这连个静态的成员只创建一次。

静态成员函数没有this指针,不能访问任何非静态成员
静态成员也是类的成员,受 public,private,provected访问限定符的限制

友元

类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数成为它的友元(friend)。如果类想把一个函数作为它的友元,只需要增加一条以friend关键字开始的函数声明语句即可。

class Time
{
	friend class Date;
public:
	Time(int a = 1)
		:_time(a)
	{}

private:
	int _time;
};

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

	void SetTime(int a)
	{
		_t._time = a;
	}

private:
	int _year;
	int _month;
	int _day;

	Time _t;
};

int main()
{
	Date a(2023, 5, 14);

	return 0;
}

上面的这个代码中,日期类是时间类的友元,所以在日期类中,可以访问时间类的成员。


友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

  • 友元的关系是单项的,不具有交换性(如上面的代码,可以在日期类中访问时间类的私有成员,但不可以在时间类中访问日期类的成员)
  • 友元关系不能传递
  • 友元关系不能继承

内部类

内部类,顾名思义就是定义在一个类中的类。内部类可以访问外部类的成员变量和成员函数,也就是说,内部类是外部类的友元。内部类可以看作是外部类的一部分,但是在外部类的成员函数或者其他外部类的代码中,不能直接使用内部类的名称, 需要使用作用域限定符。

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

	class Time
	{
	public:
		Time(int h,int m,int s)
			:_hour(h)
			,_minute(m)
			,_second(s)
		{}
	private:
		int _hour;
		int _minute;
		int _second;
	};

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

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

输出结果 12,这是因为sizeof外部类=外部类,和内部类没有任何关系

	cout << "外部类的大小" << ":" << sizeof(Date) << endl;
	cout << "内部类的大小" << ":" << sizeof(Date::Time) << endl;

输出结果 12 12

通过作用域限定符可以访问到内部类。

内部类可以定义在外部类的public,protected,private都是可以的

内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名

匿名对象

class Solve
{
public:
	Solve(int a)
	{
		cout << "Solve" << endl;
	}

	~Solve()
	{
		cout << "~Solve" << endl;
	}
};

int main()
{
	Solve a(1);
	Solve(1);
	return 0;
}

在上面代码中,a是一个有名对象,a下面的是一个匿名对象(匿名对象指的是一个没有命名的临时对象),他跟有名对象有点不同,有名对象的生命周期在当前函数局部域,而匿名对象的声明周期在当行。

匿名对象是具有常性的,const引用延长匿名对象的生命周期,声明周期为当前函数局部域。


class Solve
{
public:
	Solve()
	{
		cout << "Solve" << endl;
	}

	void Print()
	{
		cout << "----------------" << endl;
	}

	~Solve()
	{
		cout << "~Solve" << endl;
	}
};

int main()
{
	Solve().Print();
	return 0;
}

拷贝对象时一些编译器优化

在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。

比如:一个表达式中,连续构造+拷贝构造,可以优化为一个构造

隐式类型中:连续构造+拷贝构造,优化为直接构造

连续拷贝构造+拷贝构造,优化为一个拷贝构造

一个表达式中,连续拷贝构造+赋值重载,无法优化

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}

	A(const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa)" << endl;
	}
private:
	int _a;
};

void f1(A aa)
{
	;
}

A f2()
{
	A aa;
	return aa; 
}

int main()
{
	f1(1);//隐式类型
	f1(A(1));//连续构造+拷贝构造
	A a = f2();//连续拷贝构造+拷贝构造
}

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

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

相关文章

【MySQL】表的操作

目录 一.使用Cmd命令执行操作 1.使用&#xff08;mysql -uroot -p)命令进入数据库 2.创建一个角色表用于操作&#xff08;创建表之前先使用数据库&#xff09; 3.查看表 4.插入数据 5.查看表中内容 6.修改表 1.修改表名 2.修改字段名 3.修改字段的数据类型 ALTER TABL…

Vue3-黑马(十一)

目录&#xff1a; &#xff08;1&#xff09;vue3-router-布局和菜单 &#xff08;2&#xff09;vue3-进阶-router-图标二次封装-单文件组件 &#xff08;3&#xff09;vue3-进阶-router-图标的二次封装-函数式组件 &#xff08;1&#xff09;vue3-router-布局和菜单 主页做…

收藏:如何一步步成为技术领域专家

经常有人问我&#xff0c;为什么有的人工作10年仍然平台无奇&#xff0c;而有的人只用3年时间&#xff0c;就已经脱颖而出&#xff0c;成绩斐然。我说&#xff0c;是呀&#xff0c;有些参加工作多年却仍然只会复制粘贴简单业务代码&#xff0c;有些人在大学就写出Linux操作系统…

英文论文(sci)解读复现【NO.9】基于注意机制的葡萄叶片病害检测

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

(免费分享)基于微信小程序的旅游系统(带文档)

随着互联网的趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己的信息推广出去&#xff0c;最好方式就是建立自己的平台信息&#xff0c;并对其进行管理&#xff0c;随着现在智能手机的普及&#xff0c;人们对于智能手机里面的应用旅游服务软件也在不断的使用&#xff0…

vue-8:Vuex状态管理模式库 + map辅助函数简写

为什么存&#xff1a;存仓库的多组件可以数据共享 核心api this.$store 每个组件都可以获取$store this.$store.commit("同步方法名", 参数) 调用同步方法&#xff0c;修改store中的数据 this.$store.dispatch("异步方法名", 参数) 调用异步方法&#x…

分布式数据库集成解决方案

分布式数据库集成解决方案 分析访问部署扩展.1 以界面方式创建数据库&#xff08;采用DBCA&#xff09; # 背景 由于公司业务的发展&#xff0c;要求在其它三个城市设立货仓&#xff0c;处理发货业务。公司本部运行着一套用Sybase数据库的MIS系统可以实现发货&#xff0c;该系统…

【多线程】线程池

目录 线程池是什么 标准库中的线程池 描述线程池工作原理 为什么不推荐使用系统自带的线程池 实现线程池 线程池是什么 线程池就是在池子里放的线程本身&#xff0c;当程序启动时就创建出若干个线程&#xff0c;如果有任务就处理&#xff0c;没有任务就阻塞等待。 想象这…

hive集成hbase Bytes.toByte处理字段 隐射为null乱码 加#b为0问题

解决hive集成hbase Bytes.toByte处理字段 隐射为null乱码 为0问题 错误例子&#xff08;一&#xff09; create external table bigdata_student(id string,name string,age int )stored by org.apache.hadoop.hive.hbase.HBaseStorageHandler with SERDEPROPERTIES ("h…

内网渗透(七十二)之域权限维持之伪造域控

伪造域控 2022年1月10日,国外安全研究员Kaido发文称发现了一种新的伪造域控方式,安全研究员只需要新建一个机器账户,然后修改机器账户的UserAccountControl属性为8192。活动目录就会认为这个机器账户就是域控,然后就可以使用这个新建的机器账户进行DCSync操作了。由于修改…

系统开发与运行

系统开发与运行 系统分析与设计 需求分析 需求工程 结构化分析与设计 测试基础知识 系统运行与维护 软件架构介绍 系统分析概述 系统分析是一种问题求解技术&#xff0c;它将一个系统分解成各个组成部分&#xff0c; 目的是研究各个部分如何工作、交互,以实现其系统目标…

Android系统启动全流程分析

当我们买了一个手机或者平板&#xff0c;按下电源键的那一刻&#xff0c;到进入Launcher&#xff0c;选择我们想要使用的某个App进入&#xff0c;这个过程中&#xff0c;系统到底在做了什么事&#xff0c;伙伴们有仔细的研究过吗&#xff1f;可能对于Framework这块晦涩难懂的专…

数据流畅驰骋:探秘Logstash在大数据领域的卓越表现【上进小菜猪大数据系列】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 摘要&#xff1a;Logstash是大数据领域中常用的数据处理引擎&#xff0c;能够高效地采集、转换和输出数据。本文将深入介绍Logstash的基本概念、工作原理和常见应用场景&#xff0…

科学计算库-Pandas随笔【及网络隐私的方法与策略闲谈】

文章目录 8.2、pandas8.2.1、为什么用 pandas &#xff1f;8.2.2、pandas Series 类型8.2.3、pandas 自定义索引8.2.4、pandas 如何判断数据缺失&#xff1f;8.2.5、pandas DataFrame 类型8.2.6、pandas 筛选8.2.7、pandas 重新索引8.2.8、pandas 算数运算和数据对齐8.2.9、pan…

linux 内核开启调试选项

前言 嵌入式 linux 经常要编译 linux 内核&#xff0c;默认情况下编译出的内核镜像是不带调试信息的&#xff0c;这样&#xff0c;当内核 crash 打印 PC 指针和堆栈信息时&#xff0c;我们需要反汇编来确认出错位置&#xff0c;不直观。 如果内核开启了调试选项&#xff0c;我…

控制系统中的闭环带宽

控制系统中的闭环带宽是指反馈控制系统中控制器输出与被控对象输入之间的频率范围。具体来说&#xff0c;闭环带宽是在稳定性和响应速度之间做出的折衷&#xff0c;越高的闭环带宽通常意味着更快的响应速度&#xff0c;但也可能导致系统变得不稳定。 在实际应用中&#xff0c;…

HTML <base> 标签

实例 <head> <base href="http://www.w3school.com.cn/i/" /> <base target="_blank" /> </head><body> <img src="eg_smile.gif" /> <a href="http://www.w3school.com.cn">W3School<…

JAVA常用ApI - Object和Objects

文章目录 目录 文章目录 前言 一 .Object是什么&#xff1f; 二 .Object的常用方法 1.tostring 1.1 返回值 1.2 重写toString方法 3.clone(克隆) 1.克隆接口 三.Objects 总结 前言 大家好,我是最爱吃兽奶,今天给大家讲一下java中的object和object的工具类objects 那…

泰裤辣,可以利用AI测测Vue知识的掌握程度。

以下是一些常见的Vue面试题&#xff1a; 可以先试着回答&#xff0c;以下是参考答案。 1. 什么是Vue&#xff0c;它的优点是什么&#xff1f; Vue是一套用于构建用户界面的渐进式JavaScript框架&#xff0c;它以简洁的API和响应式数据绑定的特性来大大简化了前端开发过程。Vue…

Linux基本指令和操作(3)

目录 一. date指令 -- 显示时间 二. cal指令 -- 日历打印指令 三. find指令 -- 查找文件 四. grep指令 -- 行过滤指令 五. zip/unzip指令 -- 压缩和解压缩 六. tar指令 -- 解压/打包 或 查看压缩包内文件 七. bc指令 -- 计算器 八. uname指令 -- 获取电脑和操作系统相关…