【C++篇】C++类与对象深度解析(三):类的默认成员函数详解

文章目录

  • 【C++篇】C++类与对象深度解析(三)
    • 前言
      • 4. 运算符重载基本概念
        • 4.1 运算符重载的基本概念
        • 4.2 重载运算符的规则
        • 4.3 成员函数重载运算符
        • 4.4 运算符重载的优先级与结合性
        • 4.5 运算符重载中的限制与特殊情况
          • 4.5.1 不能创建新的操作符
          • 4.5.2 无法重载的运算符
          • 4.5.3 前置和后置递增运算符的重载
          • 补充: `.*`(成员指针访问运算符)
            • 介绍:
            • 示例:使用 `.*` 运算符访问成员函数
            • 示例:使用 `.*` 运算符访问成员变量
            • 不能重载 `.*` 运算符
      • 5 赋值运算符重载
        • 5.1 赋值运算符重载必须定义为成员函数
        • 5.2 有返回值,建议写成当前类类型的引用
        • 5.3 编译器自动生成的默认赋值运算符
        • 5.4 显式实现赋值运算符重载的必要性
        • 5.5 赋值运算符与析构函数的关系
          • 总结
      • 6. 取地址运算符重载
        • 6.1 const成员函数
        • 6.2 取地址运算符重载
          • 普通取地址运算符重载
          • const取地址运算符重载
          • 总结
  • 写在最后

【C++篇】C++类与对象深度解析(三)

前言

接上篇:

【C++篇】C++类与对象深度解析(二):类的默认成员函数详解

在上一篇文章中,我们讨论了C++类的默认成员函数,包括构造函数、析构函数和拷贝构造函数。本篇我们将继续探索剩余的默认成员函数,这些是C++面向对象编程中不可或缺的高级特性。掌握这些功能将帮助您更加灵活地设计和实现C++类。❤️

4. 运算符重载基本概念

4.1 运算符重载的基本概念

运算符重载允许我们为类对象自定义运算符的行为,这样当我们对类对象使用这些运算符时,它们会按照我们定义的方式执行。如果没有定义对应的运算符重载,编译器将会报错,因为它不知道如何处理这些运算符。

  • 运算符重载的定义:运算符重载是一个特殊的函数,名字是operator加上要重载的运算符。
  • 参数数量:重载函数的参数数量取决于运算符的类型。一元运算符有一个参数,二元运算符有两个参数。

示例:重载==运算符

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 重载==运算符用于比较两个Number对象是否相等bool operator==(const Number& n) const{return _value == n._value;}private:int _value;
};int main()
{Number n1(10);Number n2(10);if (n1 == n2) {cout << "两个数相等。" << endl;} else {cout << "两个数不相等。" << endl;}return 0;
}

解释

  • operator==:这个重载允许我们直接使用==来比较两个Number对象是否相等,而不需要手动检查它们的内部值。

4.2 重载运算符的规则
  • 函数的名字:重载的函数名称必须是operator加上运算符,例如operator+operator==
  • 参数和返回类型:重载的运算符函数需要根据需要设置参数和返回类型。对于二元运算符,左侧对象传给第一个参数,右侧对象传给第二个参数。

示例:重载+运算符

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 重载+运算符,用于两个Number对象相加Number operator+(const Number& n) const{return Number(_value + n._value);}void Print() const{cout << "Value: " << _value << endl;}private:int _value;
};int main()
{Number n1(10);Number n2(20);Number n3 = n1 + n2; // 使用重载的+运算符n3.Print(); // 输出: Value: 30return 0;
}

解释

  • operator+:这个运算符重载允许我们使用+运算符来相加两个Number对象,并返回一个新的Number对象。

4.3 成员函数重载运算符

如上面的例子,当运算符重载定义为类的成员函数时,第一个运算对象会隐式地传递给this指针,因此成员函数的参数数量比操作数少一个。

示例:重载-运算符

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 重载-运算符,用于两个Number对象相减Number operator-(const Number& n) const{return Number(_value - n._value);}void Print() const{cout << "Value: " << _value << endl;}private:int _value;
};int main()
{Number n1(20);Number n2(10);Number n3 = n1 - n2; // 使用重载的-运算符n3.Print(); // 输出: Value: 10return 0;
}

解释

  • operator-:这个重载允许我们使用-运算符来减去两个Number对象的值,并返回一个新的Number对象。

4.4 运算符重载的优先级与结合性

虽然我们可以改变运算符的行为,但其优先级和结合性与内置类型运算符保持一致。这意味着我们不能通过重载运算符来改变它们的运算顺序。

示例:重载*运算符

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 重载*运算符,用于两个Number对象相乘Number operator*(const Number& n) const{return Number(_value * n._value);}void Print() const{cout << "Value: " << _value << endl;}private:int _value;
};int main()
{Number n1(5);Number n2(4);Number n3 = n1 * n2; // 使用重载的*运算符n3.Print(); // 输出: Value: 20return 0;
}

解释

  • operator*:这个重载允许我们使用*运算符来相乘两个Number对象的值,并返回一个新的Number对象,其优先级还是高于重载后的+运算符。

4.5 运算符重载中的限制与特殊情况
4.5.1 不能创建新的操作符

在C++中,虽然可以重载大多数运算符,但不能创建新的操作符。也就是说,我们不能使用C++语法中没有的符号来创建新的运算符。例如,operator@是非法的,因为@符号不是C++中的有效运算符。

解释

  • 只能重载C++已有的运算符,如+, -, *, /, ==等。不能创建诸如operator@这样的运算符,因为@不属于C++的运算符集合。

示例:尝试创建一个新的操作符(会报错)

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 错误:不能定义新的运算符Number operator@(const Number& n) const{return Number(_value + n._value);}private:int _value;
};int main()
{Number n1(10);Number n2(20);// n1 @ n2; // 错误:@ 不是一个合法的C++运算符return 0;
}

结果

  • 编译器会报错,因为@不是C++中的有效运算符,不能通过operator@进行重载。
4.5.2 无法重载的运算符

在C++中,有五个运算符是不能重载的,这些运算符的行为在语言中是固定的,不能改变。

这些运算符包括:

  1. .(成员访问运算符)
  2. .*(成员指针访问运算符)见以下补充
  3. ::(作用域解析运算符)
  4. sizeof(大小计算运算符)
  5. ?:(三元条件运算符)

解释

  • 这些运算符的行为在C++中是固定的,无法通过重载改变它们的语义或使用方式。

示例:尝试重载不能重载的运算符(会报错)

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 错误:不能重载sizeof运算符int operator sizeof() const{return _value;}private:int _value;
};int main()
{Number n1(10);// int size = sizeof(n1); // 错误:无法重载sizeof运算符return 0;
}

结果

  • 编译器会报错,因为sizeof是一个固定的运算符,无法通过重载改变其行为。
4.5.3 前置和后置递增运算符的重载

在C++中,递增运算符++可以有两种形式:前置递增后置递增。它们的功能类似,但实现方式不同。

  • 前置递增:先递增,然后返回递增后的值。
  • 后置递增:先返回当前值,然后递增。

为了区分前置和后置递增运算符,C++规定在重载后置递增运算符时,必须增加一个int参数。这只是一个区分符,并没有实际用途。

示例:重载前置和后置递增运算符

前置直接操作对象,传引用返回,而后置返回副本,用传值返回

#include<iostream>
using namespace std;class Number {
public:Number(int value = 0) : _value(value) {}// 重载前置++Number& operator++(){++_value;return *this;}// 重载后置++Number operator++(int){Number tmp = *this; // 保存当前值++_value;           // 递增return tmp;         // 返回原始值}void Print() const{cout << "Value: " << _value << endl;}private:int _value;
};int main()
{Number n1(5);++n1; // 前置++n1.Print(); // 输出: Value: 6n1++; // 后置++n1.Print(); // 输出: Value: 7return 0;
}

解释

  • operator++():这是前置递增的实现。先递增,然后返回递增后的对象自身。
  • operator++(int):这是后置递增的实现。先保存当前对象的副本,然后递增,并返回副本。

结果

  • 前置递增直接修改并返回对象自身,而后置递增返回递增前的副本,之后再进行递增。

这里我们直接使用的普通++类型来实现+1操作,在之后实现了+=运算符重载后可以实现复用,这在最后类和对象的实践篇:日期类的实现会讲到


补充: .*(成员指针访问运算符)
介绍:

.* 是 C++中的成员指针访问运算符,用于通过对象访问指向该对象成员的指针。这个运算符主要用在需要通过指针访问对象的成员函数或成员变量的场景中。

在 C++ 中,.*->* 运算符提供了类似于.-> 的功能,但用于成员指针操作。因为.* 这种运算符在使用上非常特殊,因此不能进行重载。

示例:使用 .* 运算符访问成员函数

假设我们有一个类 MyClass,其中包含一个成员函数 Func,我们可以通过成员指针访问并调用这个函数。

#include<iostream>
using namespace std;class MyClass {
public:void Func() {cout << "MyClass::Func() 被调用了" << endl;}
};int main() {MyClass obj;             // 创建类对象void (MyClass::*pf)() = &MyClass::Func;  // 定义成员函数指针,并指向MyClass的Func函数// 通过对象和成员函数指针调用函数(obj.*pf)();  // 使用 .* 运算符调用成员函数return 0;
}

解释

  • void (MyClass::*pf)() = &MyClass::Func;:这行代码定义了一个指向 MyClass 成员函数的指针 pf,并将其初始化为指向 Func 函数的地址。
  • (obj.*pf)();:使用 .* 运算符,通过 obj 对象调用 pf 所指向的成员函数 Func
示例:使用 .* 运算符访问成员变量

同样的方式可以用于访问成员变量,通过成员指针操作符,我们可以通过一个对象来访问其成员变量。

#include<iostream>
using namespace std;class MyClass {
public:int value;  // 成员变量
};int main() {MyClass obj;              // 创建类对象obj.value = 42;           // 直接访问成员变量int MyClass::*pValue = &MyClass::value;  // 定义成员变量指针,并指向MyClass的value成员// 通过对象和成员变量指针访问成员变量cout << "Value: " << obj.*pValue << endl;  // 使用 .* 运算符访问成员变量return 0;
}

解释

  • int MyClass::*pValue = &MyClass::value;:这行代码定义了一个指向 MyClass 成员变量的指针 pValue,并将其初始化为指向 value 变量的地址。
  • obj.*pValue:使用 .* 运算符,通过 obj 对象访问 pValue 所指向的成员变量 value
不能重载 .* 运算符

由于 .* 运算符的特殊性,它不能被重载。.* 的行为在 C++ 语言中已经固定,主要用于通过对象访问其成员指针所指向的成员。

示例:尝试重载 .*(会报错)

#include<iostream>
using namespace std;class MyClass {
public:int value;// 错误:不能重载 .* 运算符int operator.*() const {return value;}
};int main() {MyClass obj;obj.value = 42;// 编译错误:无法重载 .* 运算符// cout << obj.* << endl;return 0;
}

结果

  • 尝试重载 .* 运算符会导致编译错误,因为这个运算符在 C++ 中是固定的,不能改变其行为。

5 赋值运算符重载

赋值运算符重载是一个特殊的运算符重载,用于将一个对象的状态复制到另一个已经存在的对象中。需要注意的是,赋值运算符重载与拷贝构造函数是不同的,拷贝构造用于初始化一个新对象,而赋值运算符则用于给已经存在的对象赋值。

5.1 赋值运算符重载必须定义为成员函数

赋值运算符重载是C++的一个特殊运算符重载,必须作为类的成员函数来定义。这是因为赋值运算符总是需要操作当前对象(this指针),因此它不能作为全局函数来实现。

示例:定义赋值运算符重载

#include<iostream>
using namespace std;class MyClass {
public:MyClass(int value = 0) : _value(value) {}// 赋值运算符重载,参数是const类型的引用MyClass& operator=(const MyClass& other) {if (this != &other) {  // 防止自我赋值_value = other._value;}return *this;  // 返回当前对象的引用,以支持链式赋值}void Print() const {cout << "Value: " << _value << endl;}private:int _value;
};int main() {MyClass obj1(10);MyClass obj2(20);obj2 = obj1;  // 调用赋值运算符重载obj2.Print(); // 输出: Value: 10return 0;
}

解释

  • operator=:这是赋值运算符的重载函数。this指针指向当前对象,other是被赋值的对象。
  • if (this != &other):检查当前对象是否与传入对象是同一个对象,如果是同一个对象,则跳过赋值操作,以避免自我赋值引起的问题。
  • return *this;:返回当前对象的引用,这允许连续的赋值操作,例如a = b = c;
5.2 有返回值,建议写成当前类类型的引用

赋值运算符重载函数通常返回当前对象的引用,这样可以安全支持链式赋值操作,即多个对象之间连续赋值的语句。

示例:支持链式赋值

#include<iostream>
using namespace std;class MyClass {
public:MyClass(int value = 0) : _value(value) {}// 赋值运算符重载,返回当前对象的引用MyClass& operator=(const MyClass& other) {if (this != &other) {_value = other._value;}return *this;}void Print() const {cout << "Value: " << _value << endl;}private:int _value;
};int main() {MyClass obj1(10);MyClass obj2(20);MyClass obj3(30);obj1 = obj2 = obj3;  // 链式赋值obj1.Print(); // 输出: Value: 30obj2.Print(); // 输出: Value: 30return 0;
}

解释

  • 在链式赋值中,obj2 = obj3 会首先执行,operator= 返回 obj2 的引用,然后 obj1 = obj2 执行,这样 obj1 最终也得到了 obj3 的值。
5.3 编译器自动生成的默认赋值运算符

如果我们没有显式定义赋值运算符重载,编译器会自动生成一个默认的赋值运算符

这个默认的赋值运算符执行的是浅拷贝操作:对于内置类型成员变量,逐个字节地复制值;对于自定义类型成员变量,则调用它们的赋值运算符重载。

示例:使用编译器生成的默认赋值运算符

#include<iostream>
using namespace std;class MyClass {
public:MyClass(int value = 0) : _value(value) {}// 未显式定义赋值运算符重载,编译器会自动生成void Print() const {cout << "Value: " << _value << endl;}private:int _value;
};int main() {MyClass obj1(10);MyClass obj2(20);obj2 = obj1;  // 使用编译器生成的默认赋值运算符obj2.Print(); // 输出: Value: 10return 0;
}

解释

  • 在这个例子中,编译器生成了一个默认的赋值运算符,它对内置类型的成员变量执行浅拷贝操作。
5.4 显式实现赋值运算符重载的必要性

在一些情况下,例如类中包含指针成员或其他动态资源,浅拷贝可能会导致问题。这时,我们需要显式实现赋值运算符重载来进行深拷贝,以确保对象的独立性。

示例:显式实现赋值运算符进行深拷贝

#include<iostream>
using namespace std;class MyClass {
public:MyClass(int value = 0) : _value(new int(value)) {}// 拷贝构造函数MyClass(const MyClass& other) {_value = new int(*other._value);}// 赋值运算符重载MyClass& operator=(const MyClass& other) {if (this != &other) {delete _value; // 删除旧的动态内存_value = new int(*other._value); // 分配新的动态内存并复制值}return *this;}~MyClass() {delete _value; // 析构函数中释放动态内存}void Print() const {cout << "Value: " << *_value << endl;}private:int* _value; // 指针类型成员变量
};int main() {MyClass obj1(10);MyClass obj2(20);obj2 = obj1;  // 使用自定义的赋值运算符进行深拷贝obj1.Print(); // 输出: Value: 10obj2.Print(); // 输出: Value: 10return 0;
}

解释

  • 在这个例子中,MyClass 类中包含一个指针成员变量 _value,我们需要自定义赋值运算符以确保进行深拷贝,即在赋值时为 _value 分配新的内存,并将值复制到新分配的内存中。
5.5 赋值运算符与析构函数的关系

如果一个类显式定义了析构函数来释放动态资源,那么它通常也需要显式定义赋值运算符重载,以避免浅拷贝带来的资源管理问题。

示例:显式实现析构函数和赋值运算符重载

#include<iostream>
using namespace std;class MyClass {
public:MyClass(int value = 0) : _value(new int(value)) {}// 拷贝构造函数MyClass(const MyClass& other) {_value = new int(*other._value);}// 赋值运算符重载MyClass& operator=(const MyClass& other) {if (this != &other) {delete _value;_value = new int(*other._value);}return *this;}// 析构函数~MyClass() {delete _value;}void Print() const {cout << "Value: " << *_value << endl;}private:int* _value;
};int main() {MyClass obj1(10);MyClass obj2(20);obj2 = obj1;  // 使用自定义的赋值运算符进行深拷贝obj1.Print(); // 输出: Value: 10obj2.Print(); // 输出: Value: 10return 0;
}

解释

  • MyClass 包含一个指针成员变量 _value,我们通过显式实现赋值运算符和析构函数来管理动态内存,确保不会因为浅拷贝导致资源泄漏或多次释放同一块内存。
总结

赋值运算符重载在管理动态资源、确保对象独立性以及支持链式赋值时非常有用。通过理解赋值运算符的特性和如何正确实现它,我们可以编写更健壮的C++程序,避免浅拷贝带来的问题。


6. 取地址运算符重载

在C++中,取地址运算符&用于获取对象的内存地址。在大多数情况下,编译器自动生成的取地址运算符重载已经足够使用。然而,在某些特殊场景下,我们可能希望控制或限制对象地址的获取方式,这时候我们就可以手动重载取地址运算符。

6.1 const成员函数

const成员函数是指用const修饰的成员函数。它主要用于确保成员函数不会修改类的成员变量,从而保证函数的只读特性。

  • 用法:将const修饰符放在成员函数的参数列表之后。
  • 效果const实际修饰的是成员函数中隐含的this指针,表示在该成员函数中不能对类的任何成员进行修改。

示例代码:const成员函数

#include<iostream>
using namespace std;class Date {
public:Date(int year = 1, int month = 1, int day = 1) : _year(year), _month(month), _day(day) {}// const成员函数,表示不会修改类成员变量void Print() const {cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main() {// 非const对象可以调用const成员函数Date d1(2024, 7, 5);d1.Print();// const对象也可以调用const成员函数const Date d2(2024, 8, 5);d2.Print();return 0;
}

解释

  • void Print() constconst修饰了Print函数,表示它不会修改Date类的成员变量。this指针的类型在这个函数中变为const Date* const,意味着它指向的对象及指针本身都不能被修改。
  • 权限的缩小const对象只能调用const成员函数,而非const对象可以调用任意成员函数,这体现了一种权限的缩小。
6.2 取地址运算符重载

取地址运算符&通常用于获取对象的地址。通过重载该运算符,可以自定义获取对象地址的方式,甚至可以禁止获取地址或返回一个伪造的地址。

普通取地址运算符重载

普通取地址运算符用于非const对象,重载后可以控制返回对象的地址。

示例代码:普通取地址运算符重载

#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* operator&() {// return this;  // 返回对象的真实地址return nullptr;  // 返回空指针,伪装地址}private:int _year;int _month;int _day;
};int main() {Date d1(2024, 7, 5);Date* p1 = &d1;  // 使用重载的取地址运算符if (p1 == nullptr) {cout << "未获取到真实地址" << endl;} else {cout << "对象的地址为: " << p1 << endl;}return 0;
}

解释

  • Date* operator&():这是普通的取地址运算符重载。可以根据需求决定是否返回对象的真实地址,也可以返回nullptr或其他伪造地址,以达到某些特定需求(如禁止获取对象地址)的目的。
const取地址运算符重载

const取地址运算符用于const对象,重载后可以控制如何返回const对象的地址。

示例代码:const取地址运算符重载

#include<iostream>
using namespace std;class Date {
public:Date(int year = 1, int month = 1, int day = 1) : _year(year), _month(month), _day(day) {}// 重载const取地址运算符const Date* operator&() const {// return this;  // 返回对象的真实地址return nullptr;  // 返回空指针,伪装地址}private:int _year;int _month;int _day;
};int main() {const Date d1(2024, 8, 5);const Date* p1 = &d1;  // 使用重载的取地址运算符if (p1 == nullptr) {cout << "未获取到真实地址" << endl;} else {cout << "对象的地址为: " << p1 << endl;}return 0;
}

解释

  • const Date* operator&() const:这是const取地址运算符重载。它同样可以控制是否返回const对象的真实地址或者伪装地址。
总结
  • 默认行为:在大多数情况下,编译器自动生成的取地址运算符已经足够使用,不需要手动重载。
  • 特殊需求:在一些特殊场景(如禁止获取对象地址)下,可以通过重载取地址运算符来自定义行为。
  • const修饰:通过const修饰符可以控制成员函数的只读特性,确保在函数中不修改类成员变量。同时,const取地址运算符重载可以用于const对象,确保其地址获取方式受到控制。

写在最后

运算符重载使C++类对象能像基本数据类型一样操作,赋予类更直观的行为。通过重载 +- 等运算符,我们可以实现对象间的运算和比较。赋值运算符尤其重要,确保对象在涉及动态资源时安全地复制。const 成员函数则提供了数据保护,避免意外修改。总的来说,运算符重载让代码更加简洁优雅,增强了程序的灵活性。


以上就是关于【C++篇】C++类与对象深度解析(三):类的默认成员函数详解的内容,到此为止我们就把类的六个默认成员函数讲解完啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

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

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

相关文章

影刀RPE学习——自动化

下载网址&#xff1a;影刀RPA - 影刀官网 (yingdao.com) 傻瓜式安装进入界面&#xff1a; 官方教程&#xff1a;影刀RPA零基础入门教程&#xff08;2024最新版&#xff09;&#xff1a;01 引入课-影刀初相识_哔哩哔哩_bilibili

我的AI工具箱Tauri版-VideoMusicCheckpointLouver音乐卡点百叶窗视频制作

本教程基于自研的AI工具箱Tauri版进行VideoMusicCheckpointLouver音乐卡点百叶窗视频制作。 视频样片《队长小翼》《沖田浩之-燃えてヒーロー》百叶窗卡点视频 《队长小翼》《沖田浩之-燃えてヒーロー》百叶窗卡点视频 该模块没有任何消耗。需要提前准备好响应的素材 该模块没…

物联网系统中环境监测设备如何检测PM2.5——快速了解粉尘传感器

物联网系统中为什么要使用粉尘传感器 物联网系统中使用粉尘传感器的原因是多方面的&#xff0c;主要体现在以下几个方面&#xff1a; 空气质量监测 保障公众健康&#xff1a;粉尘传感器能够实时监测空气中粉尘颗粒的浓度&#xff0c;特别是PM2.5和PM10等可吸入颗粒物&#xff…

【C语言零基础入门篇 - 6】:数组、字符和字符串带你探索无限可能

文章目录 数组一维数组一维数组的定义一维数组的初始化 字符数组二维数组二维数组存汉字 字符串相关函数小结 数组 特点&#xff1a; 在同一个数组中&#xff0c;所有元素都是同一个类型。可以是int、char、float、double等类型。数组是一种构造类型&#xff0c;是一批数据的…

Android14请求动态申请存储权限

Android14请求动态申请存储权限 Android14和Android15存储权限有增加多了选择部分&#xff0c;还是全部。一个小小的存储权限真的被它玩出了花来。本来Android13就将存储权限进行了3个细分&#xff0c;是图片&#xff0c;音频还是视频文件。 步骤一&#xff1a;AndroidManife…

替西帕肽;Mounjaro;Tirzepatide;CAS:2023788-19-2

【替西帕肽Tirzepatide 简介】 替西帕肽是一种GIP/GLP-1受体激动剂&#xff0c;由39个氨基酸的多肽组成。Tirzepatide (LY3298176) 是葡萄糖依赖性胰岛素营养多肽 (GIP) 和胰高血糖素样肽-1 (GLP-1) 受体双重激动剂。Tirzepatide (LY3298176) 在血糖控制和体重减轻方面的疗效明…

Acwing数据结构:单链表

单链表 主要思想&#xff1a;使用数组实现链表(而不用结构体&#xff0c;结构体代码更长&#xff0c;后续图论也是基于数组实现&#xff09;&#xff0c;即静态链表。因为动态链表使用new申请空间需要较多的时间&#xff0c;而算法要求的是以较少的时间完成任务。 单链表&…

【软件设计文档】概要设计说明书、详细设计说明书、需求分析文档,需求报告,测试报告等

1引言 1.1编写目的 1.2项目背景 1.3参考资料 2系统总体设计 2.1整体架构 2.2整体功能架构 2.3整体技术架构 2.4运行环境设计 2.5设计目标 3系统功能模块设计 3.1个人办公 4性能设计 4.1响应时间 4.2并发用户数 5接口设计 5.1接口设计原则 5.2接口实现方式 6运行设计 6.1运行模块…

软考中级软件设计师——知识产权学习记录

软考中级软件设计师——知识产权 著作权人身权著作财产权著作权侵权行为 计算机软件著作权基本知识计算机软件著作权侵权 专利地域性与专利权申请基本知识专利权侵权 职务作品委托开发商业秘密权基本知识商业秘密侵权 商标权与商标注册基本知识商标权侵权 著作权 著作权也称为…

大数据-138 - ClickHouse 集群 表引擎详解3 - MergeTree 存储结构 数据标记 分区 索引 标记 压缩协同

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

阻止冒泡事件

每一div都有一个切换事件 div里包括【复制】事件&#xff0c; 点击【复制按钮】&#xff0c;会触发【切换事件】 因为冒泡 在 Vue 3 中&#xff0c;阻止 click 事件冒泡可以使用以下常规方法&#xff1a; 1 事件修饰符&#xff1a;Vue 3 中提供了多种事件修饰符&#xff0c…

第14章 存储器的保护

第14章 存储器的保护 该章主要介绍了GDT、代码段、数据段、栈段等的访问保护机制。 存储器的保护功能可以禁止程序的非法内存访问。利用存储器的保护功能&#xff0c;也可以实现一些有价值的功能&#xff0c;比如虚拟内存管理。 代码清单14-1 该章节的代码主要实现的功能就…

科学哲学(Philosophy of Science)

GPT-4o (OpenAI) 科学哲学是一门研究科学的基本问题和本质的哲学学科&#xff0c;探讨科学方法、科学知识的性质、科学理论的发展及科学实践的意义和价值等问题。以下是科学哲学的一些关键方面和概念&#xff1a; 主要问题和概念&#xff1a; 1. 科学方法论&#xff1a; - …

大模型研发全揭秘:如何通过模型验证提升模型性能?(附详细代码)

在机器学习和深度学习的开发流程中&#xff0c;模型验证是一个关键的环节。验证集不仅用于检查模型的性能&#xff0c;还能帮助识别和解决潜在问题。本文将通过详细的代码示例和具体案例&#xff0c;逐步介绍从验证集准备、模型测试到评估指标计算的全过程。无论你是AI新手还是…

路由器接口配置DHCP实验简述

一、路由器配置 [Huawei]undo info-center enable Info: Information center is disabled. [DHCP-SERVER]sysname DHCP-Server [DHCP-Server]dis this sysname DHCP-Server undo info-center enable return [DHCP-Server]dhcp enable Info: The operation may take a few secon…

C++速通LeetCode简单第17题-爬楼梯(全网最简单)

思路要点&#xff1a;将问题转化为求斐波那契数列的第n项&#xff0c;然后迭代。 思路分析&#xff1a;最后一次爬的阶数不是1就是2&#xff0c;假设爬n阶的方法数是f(n)&#xff0c;假设最后一次爬1阶&#xff0c;那么爬前面的 n-1阶的方法数是f(n-1)&#xff1b;假设最后一次…

扩展------分布式调度任务框架XXL-JOB

目录 定时任务定时任务的应用场景定时任务的实现方式为什么要使用Xxl-job&#xff1f;有什么优点Springboot整合Xxl-job 1、下载源码2、配置admin&#xff0c;构建镜像部署在Centos上3、执行器服务4、admin调度中心创建执行器5、基于OpenJDK镜像部署Java应用程序创建一个新Spr…

muduo - 概要简述

作者&#xff1a;陈硕 编程语言&#xff1a;C 架构模式&#xff1a;Reactor 代码链接&#xff1a;GitHub - chenshuo/muduo: Event-driven network library for multi-threaded Linux server in C11 设计自述&#xff1a;https://www.cnblogs.com/Solstice/archive/2010/08…

交流电力控制电路之交流调压电路

目录 一、单相交流调压电路 1. 相控调压电路 2. 斩控调压电路 二、三相交流调压电路 1. 星形联结&#xff08;Y型联结&#xff09; 2. 支路控制三角形联结 交流变交流大纲 交流调压电路用于调节交流电的输出电压&#xff0c;广泛应用于照明、加热、电机调速等领域。根据不…

cesium入门到精通(9) 添加物体

如何在 一个点中 添加一个物体呢 我先把整体代码 粘贴在这里 <template><div id"cesiumContainer" ref"cesiumContainer"></div> </template><script setup> // yarn add cesium // 将cesium目录下的Build/Cesium4个目录拷…