C++初阶(五)--类和对象(中)--默认成员函数

news2024/10/16 12:35:08

目录

一、默认成员函数(Default Member Functions)

 二、构造函数( Constructor)

1.构造函数的基本概念

2.构造函数的特征

3.构造函数的使用

无参构造函数 和 带参构造函数

注意事项:

4.默认构造函数

隐式生成的默认构造函数:

默认构造函数的特性 :

注意事项:

5.构造函数的特性

三、析构函数(Destructor)

1.析构函数的基本概念

2.析构函数的特征

3.析构函数的使用

4.默认析构函数

5.析构顺序问题

6.析构函数特性

四、 拷贝构造函数

1.定义

2.拷贝构造函数的特性

3.拷贝构造函数的用法

对象初始化

函数返回值按值返回

4.拷贝构造函数的深拷贝与浅拷贝

5.引用传参(面试题)


一、默认成员函数(Default Member Functions)

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

class Date {};

 二、构造函数( Constructor)

1.构造函数的基本概念

构造函数是一种特殊的成员函数,它在对象创建时自动调用,用于初始化对象的成员变量。构造函数的名字必须与类名完全相同,并且没有返回类型。

注意:构造函数只是初始化对象,不开辟空间创建对象。

2.构造函数的特征

构造函数是特殊的成员函数,主要特征如下:

  • 构造函数的函数名和类名是相同的 (比如类名是 Date,构造函数名就是 Date)
  • 构造函数无返回值 (它不具有返回类型,因此不能直接返回值)
  • 构造函数支持重载 (仔细看下面的例子)
  • 会在对象实例化时自动调用对象定义出来。

3.构造函数的使用

 无参构造函数 和 带参构造函数

#include <iostream>  
using namespace std;

class MyClass 
{
public:

    MyClass() 
    {
         cout << "无参构造函数被调用" << endl;
    }

    MyClass(int val)
    {
        value = val;
        cout << "带参数的构造函数被调用,值为: " << value << endl;
    }
private:
    int value;

};

int main() 
{
    MyClass obj1; // 调用无参构造函数,注意后面没有括号哦~  
    MyClass obj2(10); // 调用带参数的构造函数  
    return 0;
}

运行结果:

解读:不给参数时就会调用 无参构造函数,给参数则会调用 带参构造函数。 

注意事项:

 构造函数是特殊的,不是常规的成员函数,不能直接调

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

int main(void)
{
    Date d1;
    d1.Date(); // 不能这么去调,构造函数是特殊的,不是常规的成员函数!

    return 0;
}

 

 如果通过无参构造函数创建对象,对象后面不用跟括号,否则就成了函数声明。 

#include <iostream>  
using namespace std;

class MyClass 
{
public:

    MyClass() 
    {
         cout << "无参构造函数被调用" << endl;
    }

    MyClass(int val)
    {
        value = val;
        cout << "带参数的构造函数被调用,值为: " << value << endl;
    }

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

private:
    int value;

};

int main() 
{
    MyClass obj1(); // 调用无参构造函数  
    obj1.Print();
    MyClass obj2(10); // 调用带参数的构造函数  
    obj2.Print();
    return 0;
}

 带上括号:

不带括号:

 这里如果调用带参构造函数,我们需要传递三个参数(这里我们没设缺省) 。 

 如果你没有自己定义构造函数(类中未显式定义),C++ 编译器会自动生成一个无参的默认构造函数。当然,如果你自己定义了,编译器就不会帮你生成了。 

class Date 
{
public:
    //如果用户显式定义了构造函数,编译器将不再生成
   /* Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }*/
    void Print()
    {
        printf("%d-%d-%d\n", _year, _month, _day);
    }

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

int main(void)
{
    Date d1;
    d1.Print();
    return 0;
}

 输出结果:

没有定义构造函数,对象也可以创建成功,因此此处调用的是 编译器默认生成的构造函数。

接下来,我们来讲一下默认构造函数。 

4. 默认构造函数

概念:

默认构造函数是一种没有参数或参数全部有默认值的构造函数。当没有为类显式定义任何构造函数时,编译器会自动生成一个默认的无参构造函数。这个构造函数通常不会执行任何初始化操作,但它是存在的,可以用于创建类的对象。

无参构造函数、全缺省构造函数、自动生成的构造函数都被称为 默认构造函数

并且 默认构造函数只能有一个!

隐式生成的默认构造函数:

#include <iostream>  
using namespace std;

class MyClass 
{
public:
    // 没有显式定义任何构造函数  
};

int main() 
{
    MyClass obj; // 调用隐式生成的默认构造函数  
    return 0;
}

在这个例子中,MyClass没有显式定义任何构造函数,因此编译器会为其生成一个默认的无参构造函数。在main函数中创建MyClass类型的对象obj时,会调用这个隐式生成的默认构造函数。

默认构造函数的特性 :

  1. 无参或全默认参数:默认构造函数要么没有参数,要么所有参数都有默认值。
  2. 自动生成:当类中没有显式定义任何构造函数时,编译器会自动生成一个默认构造函数。
  3. 初始化成员变量:虽然隐式生成的默认构造函数不会执行任何自定义的初始化操作,但它仍然会调用成员变量的默认构造函数(如果成员变量是类的对象)。

成员变量的默认构造函数调用 :代码示例

#include <iostream>  
using namespace std;

class Member 
{
public:
    Member() 
    {
        cout << "Member默认构造函数被调用" << endl;
    }
};

class MyClass 
{
private:
    Member member;
public:
    // 没有显式定义任何构造函数  
};

int main() 
{
    MyClass obj; // 调用隐式生成的默认构造函数,同时调用Member的默认构造函数  
    return 0;
}

 输出:

在这个例子中,MyClass包含了一个Member类型的成员变量。当创建MyClass类型的对象时,隐式生成的默认构造函数会调用Member的默认构造函数来初始化member。 

注意事项:

语法上无参和全缺省可以同时存在,但如果同时存在会引发二义性:

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

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

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

5.构造函数的特性

通过刚才的讲解我们知道了任何一个类的默认构造函数,只有三种:

  • 无参的构造函数
  • 全缺省的构造函数
  • 我们不写,编译器自己生成的构造函数

如果你没有自己定义构造函数(类中未显式定义),C++ 编译器会自动生成一个无参的默认构造函数。当然,如果你自己定义了,编译器就不会帮你生成了。

代码:

class Date 
{
public:
    // 让编译器自己生成一个
    void Print() 
    {
        printf("%d-%d-%d\n", _year, _month, _day);
    }

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

int main(void)
{
    Date d1;  // 这里调用的是默认生成的无参的构造函数
    d1.Print();

    return 0;
}

关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会 生成默认的构造函数。但是看起来默认构造函数又没什么用?d1对象调用了编译器生成的默 认构造函数,但是d1对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的 默认构造函数并没有什么用?

解答:

C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类 型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型,看看 下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员 函数。

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

 运行结果:

对于用户定义的类型(如类、结构体),如果它们没有定义自己的构造函数,编译器会生成一个默认的无参数构造函数(也称为“合成默认构造函数”)。这个构造函数会按成员变量在类中声明的顺序调用它们的默认构造函数(如果有的话)。

代码示例:

#include <iostream>  
#include <string>  
  
class MemberClass 
{  
public:  
    MemberClass() 
    {  
        std::cout << "MemberClass default constructor called" << std::endl;  
    }  
};  
  
class MyClass 
{  
public:  
    MemberClass member; // 用户定义类型成员变量  
    // MyClass没有定义自己的构造函数,所以编译器会生成一个默认构造函数  
};  
  
int main() 
{  
    MyClass obj; // 调用MyClass的默认构造函数,它会调用MemberClass的默认构造函数  
    return 0;  
}

 在上面的代码中,当MyClass的对象obj被创建时,它的成员变量member会被初始化,这会调用MemberClass的默认构造函数。

注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

#include<iostream>
using namespace std;
class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
		void Print()
		{
			cout << _year << "-" << _month << "-" << _day << endl;
		}
private:
	// 基本类型(内置类型)
	int _year = 2024;
	int _month = 12;
	int _day = 1;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	d.Print();
	return 0;
}

注意:构造函数遵循先定义先构造原则。 

三、析构函数(Destructor)

1.析构函数的基本概念

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

对象在销毁时会自动调用析构函数,完成对象的一些资源清理工作。

2. 析构函数的特征

1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值类型。
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

class MyClass 
{
public:
    ~MyClass() {
        // 释放资源的代码  
        std::cout << "Destructor called!" << std::endl;
    }
};

在上面的例子中,~MyClass() 是 MyClass 类的析构函数。

3.析构函数的使用

在我们前面学习栈的实现的时候,动态开辟后的内存需要手动进行释放,但是我们很有可能会忘记释放,因为即使不释放空间,程序也可以正常运行。如果使用析构函数,那么会自动调用,能够有效减少忘记释放的可能。 

#include<iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 4)//全缺省默认构造函数
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (NULL == _array)
		{
			perror("malloc fail!!!");
			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);
}

我们在设置栈的构造函数时,定义容量 capacity 时利用缺省参数默认给个4的容量,这样用的时候默认就是4,如果不想要4可以自己传。

如此一来,就可以保证了栈被定义出来就一定被初始化,用完后会自动销毁。以后就不会有忘记调用 destroy 而导致内存泄露的惨案了,这里的析构函数就可以充当销毁的作用。

4.默认析构函数

关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。

#include<iostream>
using namespace std;
class Time
{
public:
	~Time()
	{
		cout << "~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 d;
	return 0;
}
// 程序运行结束后输出:~Time()

在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数? 

解答:

main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month,_day三个是内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是:main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数。

 5.析构顺序问题

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year = 1)
	{
		_year = year;
	}

	~Date()
	{
		cout << "~Date()->" << _year << endl;
	}
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
};
void func()
{
	Date d3(3);//局部对象
	static Date d4(4);//局部的静态
}
Date d5(5);//全局对象
static Date d7(7);//全局静态
Date d6(6);
static Date d8(8);

// 局部对象(后定义先析构) -》 局部的静态 -》全局对象(后定义先析构)
int main()
{
	Date d1(1);//局部对象 
	Date d2(2);
	func();

	return 0;
}

析构函数执行顺序:局部对象(后定义先析构) -》 局部的静态 -》全局对象(后定义先析构) 

6.析构函数特性

📌 如果不自己写构造函数,让编译器自动生成,那么这个自动生成的 默认构造函数:

对于 "内置类型" 的成员变量:不会做初始化处理。
对于 "自定义类型" 的成员变量:会调用它的默认构造函数(不用参数就可以调的)初始化,如果没有默认构造函数(不用参数就可以调用的构造函数)就会报错!
 而我们的析构函数也是这样的。

📌 如果我们不自己写析构函数,让编译器自动生成,那么这个 默认析构函数:

对于 "内置类型" 的成员变量:不作处理 。
对于 "自定义类型" 的成员变量:会调用它对应的析构函数  。

四、 拷贝构造函数

在C++编程中,拷贝构造函数是一个非常重要的概念,它用于创建一个新对象,作为现有对象的副本。拷贝构造函数在对象复制、函数参数传递、返回值以及容器操作等场景中扮演着关键角色。

1.定义

拷贝构造函数是一种特殊的构造函数,它接受一个同类型的对象作为参数,并用于初始化新创建的对象。其语法如下:

类名(const 类名& 形参);
ClassName(const ClassName& other);

这里,ClassName 是类的名称,other 是传递给拷贝构造函数的参数,它是一个常量引用,以避免不必要的对象复制。

2.拷贝构造函数的特性

它也是一个特殊的成员函数,所以他符合构造函数的一些特性:

① 拷贝构造函数是构造函数的一个重载形式。函数名和类名相同,没有返回值。

② 拷贝构造函数的参数只有一个,并且 必须要使用引用传参!

3.拷贝构造函数的用法

对象初始化

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

    /* Date d2(d1); */
    Date(Date& d) 
    {         // 这里要用引用,否则就会无穷递归下去
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    void Print() 
    {
        printf("%d-%d-%d\n", _year, _month, _day);
    }

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

int main(void)
{
    Date d1(2024, 10, 9);
    Date d2(d1);          // 拷贝复制

    // 看看拷贝成功没
    d1.Print();
    d2.Print();

    return 0;
}

 运行结果:

函数返回值按值返回

class Date {
public:
    Date(int year = 0, 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() {
        std::cout << _year << "-" << _month << "-" << _day << std::endl;
    }

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

Date Birthday()
{
    Date time(2004, 10, 29);
    return time;// 可能会调用拷贝构造函数来返回对象的副本

}

int main()
{
    Date T = Birthday();// 拷贝构造函数被调用,用返回的对象副本初始化 T
    return 0;
}

在这个例子中,Birthday函数返回一个对象,当这个对象被返回并用于初始化 T 时,可能会调用拷贝构造函数来创建 T。 

4.拷贝构造函数的深拷贝与浅拷贝

除了上面提到的基本用法,拷贝构造函数还涉及到深拷贝和浅拷贝的概念。

浅拷贝

默认情况下,C++ 的拷贝构造函数执行的是浅拷贝。这意味着它只是简单地复制对象的成员变量值。如果成员变量是基本类型(如 intchar 等),那么浅拷贝没有问题。但如果成员变量是指针或引用类型,浅拷贝就可能会导致问题。

class ShallowPerson {
private:
    std::string* namePtr;
    int age;

public:
    ShallowPerson(std::string n, int a) 
    {
        namePtr = new std::string(n);
        age = a;
    }

    // 浅拷贝构造函数(默认情况下的拷贝构造函数行为)
    ShallowPerson(const ShallowPerson& other) 
    {
        namePtr = other.namePtr;
        age = other.age;
        std::cout << "浅拷贝构造函数被调用,可能会有问题哦!😕" << std::endl;
    }

    ~ShallowPerson() 
    {
        delete namePtr;
    }

    void introduce() 
    {
        std::cout << "我叫 " << *namePtr << ",我 " << age << " 岁啦!" << std::endl;
    }
};

int main() 
{
    ShallowPerson sp1("酒鬼猿", 20);
    ShallowPerson sp2 = sp1;

    sp1.introduce();
    sp2.introduce();

    // 当其中一个对象被销毁时,可能会导致另一个对象出现问题
    return 0;
}

 

 在这个例子中,浅拷贝只是复制了指针的值,而不是复制指针所指向的内容。这就导致两个对象的指针指向了同一块内存。当其中一个对象被销毁并释放内存时,另一个对象的指针就变成了悬空指针,再使用这个指针就会导致未定义的行为。

深拷贝

为了解决浅拷贝的问题,我们需要实现深拷贝。深拷贝会复制对象的所有成员变量,包括指针所指向的内容。

class DeepPerson {
private:
    std::string* namePtr;
    int age;

public:
    DeepPerson(std::string n, int a) {
        namePtr = new std::string(n);
        age = a;
    }

    // 深拷贝构造函数
    DeepPerson(const DeepPerson& other) {
        age = other.age;
        namePtr = new std::string(*(other.namePtr)); // 复制指针所指向的内容
        std::cout << "深拷贝构造函数被调用,一切都好啦!😀" << std::endl;
    }

    ~DeepPerson() {
        delete namePtr;
    }

    void introduce() {
        std::cout << "我叫 " << *namePtr << ",我 " << age << " 岁啦!" << std::endl;
    }
};


int main() {
    DeepPerson dp1("酒鬼猿", 21);
    DeepPerson dp2 = dp1;

    dp1.introduce();
    dp2.introduce();

    // 现在即使一个对象被销毁,另一个对象也不会受到影响
    return 0;
}

 

在深拷贝构造函数中,我们为新对象分配了新的内存,并将原对象指针所指向的内容复制到新内存中。这样,两个对象就拥有了各自独立的内存空间,不会相互影响。 

 5.引用传参(面试题)

面试题: 为什么必须使用引用传参呢?

解答:

当我们使用值传递的方式传递参数时,实际上是将实参复制一份传递给函数的形参。这意味着会创建一个新的对象,这个新对象是实参的副本。

假设我们有一个类 MyClass,如果拷贝构造函数不使用引用传参,如下所示:

class MyClass 
{
public:
    int value;
    MyClass(MyClass obj) 
    { 
        value = obj.value;
    }
};

当我们使用一个已有的对象去初始化另一个新对象时,比如这样的代码:

MyClass obj1;
obj1.value = 10;
MyClass obj2(obj1);

在这个过程中,会调用拷贝构造函数来初始化 obj2。但是,由于拷贝构造函数的参数是按值传递的,所以在调用拷贝构造函数时,会将 obj1 复制一份传递给拷贝构造函数的形参 obj。而这个复制的过程又会触发拷贝构造函数的调用,因为要创建形参 obj 的副本。这样就形成了一个无限递归的过程。

具体来说,当执行 MyClass obj2(obj1); 时:

  1. 首先尝试调用拷贝构造函数来创建 obj2,将 obj1 作为实参传递给拷贝构造函数。
  2. 由于拷贝构造函数是按值传递参数,所以要创建形参 obj 的副本,这就需要再次调用拷贝构造函数。
  3. 第二次调用拷贝构造函数时,又要创建新的形参副本,再次触发拷贝构造函数的调用。
  4. 这个过程会不断重复下去,直到程序耗尽栈空间而崩溃。

为了避免这种无限递归的情况,拷贝构造函数的参数应该使用引用类型,当使用引用传参时,形参只是实参的一个别名,不会创建新的对象副本。这样在调用拷贝构造函数时,就可以直接使用传入的对象进行初始化,而不会触发新的拷贝构造函数调用,从而避免了无限递归的问题。

本篇博客到此结束,如果大家浏览后发现什么错误之处,或者有什么问题,评论区留言哦~

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

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

相关文章

恢复已删除文件的 10 种安卓数据恢复工具

由于我们现在在智能手机上存储了大量重要文件&#xff0c;因此了解数据恢复工具变得很重要。您永远不会知道什么时候需要使用 安卓 数据恢复工具。 由于不乏 Windows 数据恢复工具&#xff0c;因此从崩溃的计算机中恢复文件很容易。但是&#xff0c;当涉及到从 安卓恢复数据时…

大数据-171 Elasticsearch ES-Head 与 Kibana 配置 使用 测试

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Go语言Gin框架的常规配置和查询数据返回json示例

文章目录 路由文件分组查询数据库并返回jsonservice层controller路由运行效果 启动多个服务 在 上一篇文章《使用Go语言的gorm框架查询数据库并分页导出到Excel实例》 中主要给大家分享了较多数据的时候如何使用go分页导出多个Excel文件并合并的实现方案&#xff0c;这一篇文章…

unity学习-全局光照(GI)

在全局光照&#xff08;Lighting&#xff09;界面有两个选项 Realtime Light&#xff08;实时光照&#xff09;&#xff1a;在项目中会提前计算好光照以及阴影的程序&#xff0c;当你需要调用实时全局光照的时候会将程序调用出来使用 Mixed Light&#xff08;烘焙光照&#x…

如何利用kafka实现高效数据同步?

在我们之前的文章有详细介绍过Kafka的结构、特点和处理方式。具备告诉处理能力的kafka被利用在数据同步和数据传输上&#xff0c;今天来说下kafka是怎么实现高效的数据同步和传输。 一、可靠的数据传输 1. 持久性保证&#xff1a;Kafka 将数据持久化到磁盘上&#xff0c;即使在…

汽车管理系统——主界面制作

目录 主界面需要有什么&#xff1f;然后要做什么&#xff1f;添加两个主菜单&#xff08;声明&#xff09;下一步应该干什么&#xff1f;能够跳转到文件有哪几个动作&#xff1f;动作如何声明&#xff1f;为什么用选择声明指针&#xff0c;不选择直接声明这个对象&#xff1f; …

算力基础篇:从零开始了解算力

什么是算力 算力即计算能力&#xff08;Computing Power&#xff09;&#xff0c;狭义上指对数字问题的运算能力&#xff0c;而广义上指对输入信息处理后实现结果输出的一种能力。虽然处理的内容不同&#xff0c;但处理过程的能力都可抽象为算力。比如人类大脑、手机以及各类服…

git 与 github 同步

1.配置账户 git config --global user.name "你的用户名" git config --global user.email "你的邮箱" 2.输入命令创建ssh key $ ssh-keygen -t rsa -C "邮箱" //你自己注册GitHub的邮箱 输入命令之后提示输入密码&#xff0c;回车直到出现…

C++类(3)

1.如果一个类什么成员都没有&#xff0c;简称空类 但是空类真的什么都没有吗&#xff1f; 并不是&#xff0c;任何类什么都不写&#xff0c;编译器会自动生成以下6个默认成员函数 1.构造函数 class Date { public:void Init(int year, int month, int day){_year year;_mo…

kubernetes简介及安装部署

目录 一、kubernetes简介 1、k8s的概念 2、k8s各个组件及用途 3、k8s各组件之间的调用关系 4、k8s常用名词概念 5、k8s的分层架构 二、kubernetes安装部署 1、k8s集群环境搭建 2、本地解析、swap禁用 3、安装docker 4、复制harbor仓库中的证书并启动docker 5、设定d…

基于Cesium.js的可视化大屏,效果绝对的震撼!

基于 Cesium.js 的可视化大屏确实能带来震撼的效果。Cesium.js 强大的三维渲染能力&#xff0c;能够逼真地呈现地理信息和各种数据模型。 在大屏上&#xff0c;广袤的地形地貌、精细的建筑模型以及动态的数据展示&#xff0c;仿佛将观众带入一个全新的虚拟世界。无论是用于地理…

网络分析仪——提升网络性能的关键工具

目录 什么是网络分析仪&#xff1f; 1. 实时流量监控 2. 历史数据回溯分析 3. 网络性能关键指标监测 4. 可视化界面与报告生成 总结 在当今的数字化世界&#xff0c;网络的稳定性和性能直接影响企业的运营效率。网络拥堵、延迟和丢包等问题会导致用户体验的下降&#xff…

“屏” 步青云:轻松开启录屏功能,Windows 实例教学

你知道 Windows 的录屏功能怎么打开吗&#xff1f;在当今数字化时代&#xff0c;录屏功能成为了许多人工作、学习和娱乐中的得力助手。无论是制作教学视频、记录游戏精彩瞬间&#xff0c;还是为线上会议留存资料&#xff0c;掌握录屏技能都至关重要。今天我们不仅会介绍 Window…

springboot智能网上问诊系统-计算机毕业设计源码99634

摘要 智能网上问诊系统作为医疗健康领域的重要应用之一&#xff0c;为患者提供了便捷的医疗服务途径。本研究旨在基于Springboot框架设计和实现一套智能网上问诊系统&#xff0c;结合医疗专业知识&#xff0c;实现患者与医生之间的在线咨询和诊疗服务。 通过对Springboot框架…

如何从模块内部运行 Pytest

在 Python 中&#xff0c;pytest 是一个强大的测试框架&#xff0c;用于编写和运行测试用例。通常我们会在命令行中运行 pytest&#xff0c;但是有时你可能希望从模块或脚本的内部运行 pytest&#xff0c;比如为了自动化测试或集成到某个工作流程中。 1、问题背景 当你从模块…

网络爬虫-数美滑块验证码

仅供研究学习使用。 今天带来的是数美滑块验证码的逆向 目标站 --> 传送门 解决此类验证码 首先要解决滑动距离的判定 无论是使用selenium还是使用协议的方式来破解 都绕不开滑动距离的识别 滑动距离可以参考以前我博客上的方式&#xff0c;或者找一找开源的一些算法&am…

秋招突击——8/6——万得数据面试总结

文章目录 引言正文面经整理一1、讲一下java的多态&#xff0c;重载&#xff0c;重写的概念&#xff0c;区别2、说一下Java的数组&#xff0c;链表的结构&#xff0c;优缺点3、创建java线程的方式有哪些&#xff0c;具体说说4、创建线程池呢、每个参数的意义5、通过那几种方式保…

java基础(5)继承与多态

目录 ​编辑 1.前言 2.正文 2.1继承 2.1.1继承概念 2.1.2继承语法 2.1.3子类访问父类 2.1.4super关键字 2.2多态 2.2.1多态概念 2.2.2多态条件 2.2.3重写 2.2.4向上转型与向下转型 2.2.5为什么要使用多态 3.小结 1.前言 哈喽大家好啊&#xff0c;今天继续来为大…

汽车开发流程管理工具赋能安全与质量

随着数字化、人工智能、自动化系统及物联网技术的迅速发展&#xff0c;工程驱动型企业正面临重大转型挑战&#xff0c;亟需加速并深化其变革步伐。众多企业正试图通过采用基于模型的系统工程(MBSE)、产品线工程(PLE)、ASPICE、安全、网络安全、软件定义汽车、敏捷和精益开发实践…

微信小程序上传组件封装uploadHelper2.0使用整理

一、uploadHelper2.0使用步骤说明 uploadHelper.js ---上传代码封装库 cos-wx-sdk-v5.min.js---腾讯云&#xff0c;对象存储封装库 第一步&#xff0c;下载组件代码&#xff0c;放置到自己的小程序项目中 第二步、 创建上传对象&#xff0c;执行选择图片/视频 var _this th…