【C++】构造函数、初始化列表,析构函数,拷贝构造函数,运算符重载

 注:本博客图片来源于学习笔记: 学习笔记icon-default.png?t=N7T8https://gitee.com/box-he-he/learning-notes

完整思维导图请前往该博主码云下载。


目录

 注:本博客图片来源于学习笔记: 学习笔记https://gitee.com/box-he-he/learning-notes

完整思维导图请前往该博主码云下载。

一、构造函数

构造函数的形式及其使用:

初始化列表:

explicit关键字

二、析构函数

1 .概念

2. 特性

析构函数的调用顺序

三、拷贝构造函数

特性:

四、运算符重载(部分)

1、概念

2、赋值运算符重载

3、前置++和后置++的实现


 

一、构造函数

构造函数是一种特殊的成员函数,在创建对象时自动调用,用于初始化对象的成员变量和执行其他必要的操作。它的名称与类名相同,没有返回类型,并且可以被重载。

构造函数有以下几个重要的特点:

  1. 构造函数的名称与类名相同,包括大小写和命名空间。
  2. 构造函数没有返回类型。
  3. 构造函数可以被重载,即可以定义多个具有不同参数列表的构造函数。
  4. 构造函数可以有默认参数,从而允许在创建对象时省略某些参数。
  5. 构造函数可以有任意数量的初始化列表,用于按照指定顺序初始化对象的成员变量。
  6. 构造函数可以访问类的所有成员变量和成员函数。
  7. 构造函数在创建对象时自动调用,无需手动调用。
  8. 对象的整个生命周期只调用一次。

构造函数主要用于以下几个方面(功能):

  1. 初始化成员变量:构造函数通过参数或初始化列表来初始化对象的成员变量,确保对象在创建时具有特定的初始值。
  2. 分配内存或资源:如果对象需要动态分配内存或管理其他资源(如文件句柄),构造函数可以在创建对象时进行相应的操作,从而确保对象可以正确地使用这些资源。
  3. 执行必要的操作:有时候,创建对象可能需要执行一些必要的操作,比如打开文件等,构造函数可以在创建对象时执行这些操作。

需要注意以下几点:

  1. 一个类可以有多个构造函数,它们具有不同的参数列表。这被称为构造函数的重载。
  2. 如果没有显式地定义构造函数,编译器会自动生成一个默认构造函数,但它只会对自定义类型变量进行默认初始化,对内置类型(int, double, float等)无法初始化。
  3. 编写构造函数时应该根据类的需求来初始化成员变量,并且可以根据需要执行其他必要的操作。
  4. 如果自定义了构造函数,编译器将不再生成默认构造函数。如果需要同时拥有默认构造函数和自定义构造函数,可以提供默认参数或者显式定义一个无参数的默认构造函数。

构造函数的形式及其使用:

默认构造函数包括:1、无参构造函数;2、全缺省的构造函数;3、编译器默认生成的构造函数 

当用户自己定义构造函数时 ,必须存在一个默认构造函数。

构造函数的使用:

 class Date
 {
  public:
      // 1.无参构造函数(默认构造函数)
      Date()
     {}
  
      // 2.带参构造函数
      Date(int year, int month, int day)
     {
          _year = year;
          _month = month;
          _day = day;
     }

    // 3.全缺省的构造函数(默认构造函数)
     Date(int year = 2024, int month = 2, int day = 6)
     {
          _year = year;
          _month = month;
          _day = day;
     }
    
    // 4.编译器默认生成的构造函数(默认构造函数)

  private:
      int _year;
      int _month;
      int _day;
 };
  
  void TestDate()
 {
      Date d1; // 调用无参构造函数
      Date d2(2015, 1, 1); // 调用带参的构造函数
  
      // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
      // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
      // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
      Date d3();
 }

需要注意的是全缺省的构造函数和无参的构造函数都属于默认构造函数,不能同时存在。

同时 函数2 与 函数3 无法构成函数重载,会造成函数的重定义,也无法同时存在。

 补充:由于编译器默认生成的构造函数无法对内置类型进行初始化,在C++11标准中,对此引入了解决方案:在变量声明时可以为其提供默认值。

 class Date
 {
 
  private:
      int _year = 2024;
      int _month = 2;
      int _day = 6;
 };
  
  void TestDate()
 {
      Date d; // 此时d的私有成员初始化为2024/2/6
 }

 

初始化列表:

1、基本形式

初始化列表:以一个 冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个 " 成员变量 " 后面跟
一个 放在括号中的初始值或表达式。
class Date
{
public:
Date(int year, int month, int day)
 : _year(year)
 , _month(month)
 , _day(day)
 {

 }

private:
int _year;
int _month;
int _day;
};
【注意】
1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
  1. 引用成员变量
  2. const成员变量
  3. 自定义类型成员(且该类没有其默认构造函数时)        
class A
{
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a;
};
class B
{
public:
	B(int a, int ref)
		:_aobj(a)
		, _ref(ref)
		, _n(10)
	{}
private:
	A _aobj;  // 没有默认构造函数的自定义类型
	int& _ref; // 引用
	const int _n; // const 
};

特性:

1、即使不在初始化列表中初始化自定义类型成员,其也会在初始化列表中隐式地调用其构造函数进行初始化。

2、初始化列表的执行顺序是其在类中的声明顺序,与初始化列表中的顺序无关。

explicit关键字

explicit 是一个关键字,用于修饰单参数构造函数,它可以防止编译器进行隐式的类型转换。在 C++ 中,当我们定义一个单参数构造函数时,编译器会自动进行隐式类型转换,将参数类型转换为目标类型,然后调用该构造函数来创建对象。而使用 explicit 关键字修饰的构造函数将被标记为禁止隐式类型转换。

下面是两个具体的示例来说明 explicit 关键字的作用:

1、单参构造函数

class MyClass {
public:
    explicit MyClass(int x) 
        : value(x) 
    {
    }
  
    int getValue() const {
        return value;
    }

private:
    int value;
};

int main() {
    MyClass obj1(5);       // 直接调用带有 int 参数的构造函数
    int val1 = obj1.getValue();
  
    MyClass obj2 = 10;    // 编译错误!禁止隐式类型转换
    int val2 = obj2.getValue();
  
    return 0;
}

在上述示例中,MyClass 类定义了一个带有单参数的构造函数,并使用 explicit 关键字进行修饰。这意味着我们只能通过显式地调用构造函数来创建对象,而不能进行隐式的类型转换。在 main 函数中,我们可以看到以下几点:

  1. 创建 obj1 对象时,我们直接调用了构造函数,不会发生隐式类型转换。这是合法的。

  2. 尝试使用 obj2 = 10; 进行从 int--->MyClass 隐式类型转换时,编译器会抛出错误。因为我们使用了 explicit 关键字,禁止隐式类型转换。

2、半缺省的构造函数

class MyClass {
public:
    //虽然有多个参数,但是创建对象时后两个参数可以不传递,使用explicit修饰,
   // 不具有类型转换作用,编译不通过
    explicit MyClass(int x, int y = 1, int z = 1) 
        : value(x)
        , data(y)
        , temp(z)
    {
    }
  
    int getValue() const {
        return value;
    }

private:
    int value;
    int data;
    int temp;
};

int main() {
    MyClass obj1(5);       // 直接调用带有 int 参数的构造函数
    int val1 = obj1.getValue();
  
    MyClass obj2 = 10;    // 编译错误!禁止隐式类型转换
    int val2 = obj2.getValue();
  
    return 0;
}

二、析构函数

1 .概念

通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的?              

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由    

编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

【注意】:析构函数只负责销毁占用的额外资源,即额外申请的内存空间,例如:malloc,new等。而对象本身,如果定义在函数中,则其本身存在于栈区中,随着函数的栈帧一同销毁,与析构函数无关。

2. 特性

析构函数是特殊的成员函数,其特征如下:

1. 析构函数名是在类名前加上字符 ~。

2. 无参数无返回值类型。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构

函数不能重载

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

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)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}

    //析构函数
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _size;
};
void TestStack()
{
	Stack s;
	s.Push(1);
	s.Push(2);
}

 

析构函数的调用顺序

  


三、拷贝构造函数

拷贝构造函数(Copy Constructor)是一种特殊的构造函数,它接受一个对象作为参数,用于创建一个新的对象,这个新对象与原始对象具有相同的值。

在C++中,如果我们没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。默认拷贝构造函数执行的是逐个成员的拷贝,将源对象的每个成员变量的值复制给新创建的对象。

以下是一个简单的示例来说明拷贝构造函数的用法:

class MyClass {
public:
    int value;

    // 拷贝构造函数
    MyClass(const MyClass& other) {
        value = other.value;
    }
};

int main() {
    MyClass obj1;
    obj1.value = 10;

    MyClass obj2(obj1);  // 使用拷贝构造函数创建新对象
    // 或者 MyClass obj2 = obj1;

    return 0;
}

在上述示例中,我们定义了一个名为 MyClass 的类,并在其中定义了一个拥有一个整数成员变量 value 的对象。然后我们在 main 函数中创建了两个对象 obj1 和 obj2

  • obj1 是通过默认构造函数创建的,并将 value 设置为 10。

  • obj2 是通过拷贝构造函数创建的,它的参数是另一个 MyClass 对象 obj1。在拷贝构造函数中,我们将 obj1 的值复制给了 obj2

需要注意的是,拷贝构造函数的参数应该是一个 const 引用(const MyClass& other),以确保不会修改被传递的源对象。

拷贝构造函数在以下情况下会被隐式调用:

  1. 通过赋值运算符(=)进行对象的初始化。
  2. 将一个对象作为函数的参数传递给另一个对象。
  3. 从一个函数返回对象时。

需要注意的是,当类中包含指针成员变量时,需要手动定义拷贝构造函数,以确保指针指向独立的内存,避免浅拷贝引发的指针悬挂问题。

 

特性:

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)   // 正确写法

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

 

 为什么值传递会引起无穷递归呢?为什么引用不会呢?

  答:假如参数不是引用,是值传递,那么传递给函数的值其实就是实参的一个临时拷贝,那在对实参进行临时拷贝时还是需要再次去调用我Date类里的拷贝构造函数,由于一直进行的是值传递,所以这个过程是无限递归的。但是如果拷贝构造函数的参数是对实参的引用,就不需要对实参再进行临时拷贝。引用是实参的一个别名,他们指向的也是同一块内存,所以不需要传递值,而是通过实参的引用来对实参的内存进行读写。

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 = 1970;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d1;
	// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
	// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构
	//造函数
	Date d2(d1); // Date d2 = d1; 也是默认调用的拷贝函数
	return 0;
}

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

4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?

当然像日期类这样的类是没必要的。

但是对于初始化时成员需要额外申请内存的类,此时我们使用默认拷贝函数会发生程序崩溃,这时我们必须手动创建一个拷贝构造函数进行深拷贝。例如下面的栈class Stack;

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;
	}
    
    // 如果我们在这只是进行简单的值拷贝,程序将会崩溃
	Stack(const Stack& s)
	{
		_array = new DataType[_capacity];
		memcpy(_array, s._array, _size * sizeof(DataType));
		_size = s._size;
		_capacity = s._capacity;
	}
	void Push(const DataType& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
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. 拷贝构造函数典型调用场景:     

  • 使用已存在对象创建新对象

  • 函数参数类型为类类型对象

  • 函数返回值类型为类类型对象

class MyClass {
public:
    int value;

    // 拷贝构造函数
    MyClass(const MyClass& other) {
        value = other.value;
    }
};

MyClass Test(const MyClass obj3)
{
    MyClass temp;

    return temp; // 函数返回值类型为类类型对象
                 // 由于temp为局部变量,在函数结束后不存在,所以需对temp进行临时拷贝,
                 // 返回值的实质是temp的一份临时拷贝
}

int main() {
    MyClass obj1;
    obj1.value = 10;

    MyClass obj2(obj1);  // 或者 MyClass obj2 = obj1;使用已存在的对象创建新对象
    
    Test(obj2);          // 函数的参数类型为类类型对象
    
    return 0;
}

四、运算符重载(部分)

1、概念

C++ 为了增强代码的可读性引入了运算符重载 运算符重载是具有特殊函数名的函数 ,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型: 返回值类型  operator 操作符 ( 参数列表 )
【注意】:
  1. 不能通过连接其他符号来创建新的操作符:比如operator@
  2. 重载操作符必须有一个类类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数数目少 1 ,因为成员函数的第一个参数为隐
    藏的 this
  5. .* :: sizeof ?: . 注意以上5个运算符不能重载。

2、赋值运算符重载


1、重载运算符的格式

  • 参数类型:const T&,传递引用可以提高传参效率

  • 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值

  • 检测是否自己给自己赋值

  • 返回*this :要复合连续赋值的含义

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;
	}
	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

 

2. 赋值运算符只能重载成类的成员函数不能重载成全局函数

【原因】:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现
一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值
运算符重载只能是类的成员函数。

【注意】:如果需要在全局中重载其他运算符,需要给两个参数。因为只有类的非静态成员函数具有this指针,全局函数没有。

3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。

【注意】:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符
重载完成赋值。
 

3、前置++和后置++的实现

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	// 前置++:返回+1之后的结果
	// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
	Date& operator++()
	{
		_day += 1;
		return *this;
	}
	// 后置++:
	// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
	// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
	//自动传递
		// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存
		//一份,然后给this + 1
		// 而temp是临时对象,因此只能以值的方式返回,不能返回引用
	Date operator++(int)
	{
		Date temp(*this);
		_day += 1;
		return temp;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d;
	Date d1(2022, 1, 13);
	d = d1++; // d: 2022,1,13 d1:2022,1,14
	d = ++d1; // d: 2022,1,15 d1:2022,1,15
	return 0;
}

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

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

相关文章

带你实现用自己域名打开Tomcat

文章目录 Tomcat1.1、Tomcat 下载1.2、Tomcat 文件图解1.3、 启动或关闭 Tomcat1.3.1、 启动1.3.2、 关闭程序2.1、 修改端口号2.2、修改主机名称Tomcat 1.1、Tomcat 下载 首先去Tomcat 官网下载找到我们需要下载的版本 1.2、To

PKI - 02 对称与非对称密钥算法

文章目录 概述对称密钥算法凯撒密码优点缺点 非对称密钥算法工作原理优点缺点 非对称密钥的的用途一&#xff1a; 一种简单而优雅的“混合加密”解决方案加密解密 非对称密钥的的用途二&#xff1a; 数字签名工作原理工作示意图 扩展 DSA vs RSA 概述 对称密钥算法和非对称密钥…

jvm体系结构

一、Jvm 的介绍 1、JVM体系结构 2、JVM运行时数据区 3、JVM内存模型 JVM运行时内存 共享内存区 线程内存区 3.1、共享内存区 共享内存区 持久带(方法区 其他) 堆(Old Space Young Space(den S0 S1)) 持久代&#xff1a; JVM用持久带&#xff08;Permanent Space&…

使用CICFlowMeter 实现对pcap文件的特征提取【教程】

使用CICFlowMeter 实现对pcap文件的特征提取【教程】 针对现有的关于CICFlowMeter 的使用教程不够全面&#xff0c;一些细节没有展示&#xff0c;我将结合网络上的相关资料和实际的经历&#xff0c;提供一些经验和建议。 configuration information --------------- Windows…

污水处理设备数据分析:潜在市场容量高达1000亿

随着国家可再生能源激励政策和中长期发展规划的不断贯彻落实&#xff0c;一些大型能源投资公司、房地产开发商、装备制造龙头企业和物流运营商瞄准了污水处理设备产业的巨大潜在市场&#xff0c;纷纷加入到了污水处理设备建设的行列。我国污水处理设备行业发展重点已从农户自用…

时间序列之趋势

什么是趋势&#xff1f; 在时间序列中&#xff0c;趋势成分表示序列均值持续的、长期的变化。趋势是一个序列中移动最慢的部分&#xff0c;但却代表最重要的时间尺度。在产品销售的时间序列中&#xff0c;随着越来越多的人逐年了解该产品&#xff0c;市场扩张就可能会产生增长…

JavaScript ATM取款机

①&#xff1a;循环的时候&#xff0c;需要反复提示输入框&#xff0c;所以提示框写到循环里面 ②&#xff1a;退出的条件是用户输入了 4&#xff0c;如果是4&#xff0c;则结束循环&#xff0c;不在弹窗 ③&#xff1a;提前准备一个金额预先存储一个数额 ④&#xff1a;取钱…

【敏感词】敏感词检测功能v1.1.0版本正式上线

背景 为了解决系统发布信息时人工审核成本高的问题&#xff0c;开发一个敏感词检测系统。该系统能够自动检测用户输入的内容中是否包含敏感词&#xff0c;从而减少不合规内容的发布&#xff0c;降低人工审核成本。通过实施这个系统&#xff0c;可以提高信息发布的效率和准确性…

文献速递:肿瘤分割---- 优先注意网络,用于医学图像中多病变分割

文献速递&#xff1a;肿瘤分割---- 优先注意网络&#xff0c;用于医学图像中多病变分割 Title 题目 Prior Attention Network for Multi-Lesion Segmentation in Medical Images 优先注意网络&#xff0c;用于医学图像中多病变分割 Abstract 摘要 —The accurate segmen…

【C++】win11,OpenCV安装教程(VS2022)

1.下载 首先进入官网&#xff0c;下载对应的安装包&#xff0c;苹果系统就选IOS pack&#xff0c;微软系统就选Windows 下载地址&#xff1a;Releases - OpenCV 不方便外网下载的话可以下载我分享的百度网盘资源&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1lV7l…

学生信息|基于Springboot的学生信息管理系统设计与实现(源码+数据库+文档)

学生信息管理系统目录 目录 基于Springboot的学生信息管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员登录 2、课程管理 3、公告信息管理 4、公告类型管理 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、…

阿里资深摸鱼测试工程师推荐——Web自动化测试学会这一招,下班早一小时

前 言 大家都知道&#xff0c;我们在通过 Selenium 执行 Web 自动化测试时&#xff0c;每次都需要启动/关闭浏览器&#xff0c;如果是多线程执行还会同时打开多个&#xff0c;比较影响工作的正常进行。那有没有办法可以不用让浏览器的自动化执行干扰我们的工作呢&#xff1f; …

seatunnel数据集成(一)简介与安装

seatunnel数据集成&#xff08;一&#xff09;简介与安装seatunnel数据集成&#xff08;二&#xff09;数据同步seatunnel数据集成&#xff08;三&#xff09;多表同步seatunnel数据集成&#xff08;四&#xff09;连接器使用 1、背景 About Seatunnel | Apache SeaTunnel …

【Spring基础】从0开始学习Spring(2)

前言 在上篇文章&#xff0c;我已经讲了Spring中最核心的知识点&#xff1a;IoC&#xff08;控制反转&#xff09;以及DI&#xff08;依赖注入&#xff09;。这篇文章&#xff0c;我将讲一下关于Spring框架中的其它比较琐碎但是又还是挺重要的知识点&#xff0c;因此&#xff…

【类与对象(中)】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 1.类的6个默认成员函数 2. 构造函数 2.1 概念 2.2 特性 3.析构函数 3.1 概念 3.2 特性 4. 拷贝构造函数 4.1 概念 4.2 特征 引用 常引用 5.赋值运算符重载 5.1…

Excel——高级筛选匹配条件提取数据

一、筛选多条件 Q&#xff1a;筛选多个条件&#xff0c;并将筛选出的内容复制到其他区域 点击任意一个单元格 点击【数据】——【筛选】——【高级筛选】 选择【将筛选结果复制到其他位置】——在【列表区域】 鼠标选择对应的区域位置&#xff0c;条件区域一定要单独写出来&a…

DevOps落地笔记-19|响应速度:天下武功,唯快不破

上一课时介绍一个团队应该具备什么样的能力&#xff0c;以及如何度量团队的交付效能。事实上&#xff0c;团队的能力在一定程度上反映了软件的交付能力&#xff1b;而响应速度则是企业能否快速占领市场的重要因素。试想一下&#xff0c;有两个企业都发现了市场上的机会&#xf…

【数据结构和算法】--- 基于c语言排序算法的实现(1)

目录 一、排序的概念及其应用1.1排序的概念1.2 排序的应用1.3 常见的排序算法 二、插入排序2.1直接插入排序2.2 希尔排序2.2.1 预排序2.2.2 缩小gap2.2.3 小结 三、选择排序3.1 直接选择排序3.2 堆排序 一、排序的概念及其应用 1.1排序的概念 排序&#xff1a; 所谓排序&…

作业2.6

一、填空题 1、一个类的头文件如下所示&#xff0c;num初始化值为5&#xff0c;程序产生对象T&#xff0c;且修改num为10&#xff0c;并使用show()函数输出num的值10。 #include <iostream.h> class Test { private: static int num; public: Test(int); void sh…

Flink SQL Client 安装各类 Connector、Format 组件的方法汇总(持续更新中....)

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…