剖析【C++】——类与对象(中)——小白篇—超详解

 

目录

1.类的6个默认成员函数:

1. 默认构造函数(Default Constructor)

2. 析构函数(Destructor)

3. 拷贝构造函数(Copy Constructor)

4. 拷贝赋值运算符(Copy Assignment Operator)

5. 移动构造函数(Move Constructor)

2.构造函数详解

2.1 构造函数的概念

示例类:Date

2.2 构造函数的特性

示例代码:构造函数重载

使用构造函数

编译器生成的默认构造函数

C++11中的改进

总结

3.析构函数详解

3.1 析构函数的概念

示例类:Date

3.2 析构函数的特性

示例代码:编译器自动生成的析构函数

资源管理示例:Stack类

总结

4.拷贝构造函数详解

4.1 拷贝构造函数的概念

示例类:Date

4.2 拷贝构造函数的特征

浅拷贝与深拷贝

示例代码:浅拷贝与深拷贝

拷贝构造函数的典型调用场景

总结

5.赋值运算符重载详解

5.1 运算符重载概述

示例:运算符重载函数原型

5.2 赋值运算符重载

赋值运算符重载格式

示例类:Stack

赋值运算符重载的注意事项

前置++和后置++重载

示例代码:前置和后置自增运算符重载

总结

6.日期类的实现

1. 定义Date类

2. 详细解析每个部分

2.1 构造函数

2.2 拷贝构造函数

2.3 赋值运算符重载

2.4 析构函数

2.5 显示日期

7.深度剖析C++中的const成员函数

问题1: const对象可以调用非const成员函数吗?

问题2: 非const对象可以调用const成员函数吗?

问题3: const成员函数内可以调用其它的非const成员函数吗?

问题4: 非const成员函数内可以调用其它的const成员函数吗?

示例代码

解释

构造函数和成员变量

非const成员函数

const成员函数

非const成员函数调用const成员函数

const成员函数尝试调用非const成员函数

main函数示例

8.取地址及const取地址操作符重载

1. 取地址运算符(&)

2. const取地址运算符

示例代码

代码解释

运行示例


1.类的6个默认成员函数:

在C++中,即使一个类没有定义任何成员或成员函数,编译器仍会为其生成以下6个默认成员函数。下面是对这些默认成员函数的简易分析和代码示例。

1. 默认构造函数(Default Constructor)

默认构造函数在创建对象时被调用。如果类中没有定义任何构造函数,编译器会自动生成一个默认的无参构造函数。

class MyClass {// 编译器会生成一个默认构造函数
};MyClass obj; // 调用默认构造函数
2. 析构函数(Destructor)

析构函数在对象被销毁时调用。编译器会生成一个默认的析构函数来清理资源。

class MyClass {// 编译器会生成一个默认析构函数
};{MyClass obj; // 析构函数在作用域结束时被调用
}
3. 拷贝构造函数(Copy Constructor)

拷贝构造函数用于创建一个新的对象作为现有对象的副本。如果没有定义拷贝构造函数,编译器会生成一个默认的。

class MyClass {// 编译器会生成一个默认的拷贝构造函数
};MyClass obj1;
MyClass obj2 = obj1; // 调用默认拷贝构造函数
4. 拷贝赋值运算符(Copy Assignment Operator)

拷贝赋值运算符用于将一个对象的值赋给另一个对象。如果没有定义拷贝赋值运算符,编译器会生成一个默认的。

class MyClass {// 编译器会生成一个默认的拷贝赋值运算符
};MyClass obj1;
MyClass obj2;
obj2 = obj1; // 调用默认拷贝赋值运算符
5. 移动构造函数(Move Constructor)

移动构造函数在C++11中引入,用于从一个临时对象中“偷取”资源。如果没有定义移动构造函数,编译器会生成一个默认的。

class MyClass {// 编译器会生成一个默认的移动构造函数
};MyClass obj1;
MyClass obj2 = std::move(obj1); // 调用默认移动构造函数

2.构造函数详解

构造函数是C++中的一个重要概念,它使对象在创建时自动初始化。以下是对构造函数的详细解释和代码示例,帮助初学者深入理解其原理和使用方法。

2.1 构造函数的概念

构造函数是一个特殊的成员函数,名字与类名相同。当创建类类型对象时,编译器会自动调用构造函数,以保证每个数据成员都有一个合适的初始值,并且在对象的整个生命周期内只调用一次。

示例类:Date

假设我们有一个 Date 类,需要在创建对象时设置日期信息。

class Date {
public:Date(int year, int month, int day) { // 构造函数_year = year;_month = month;_day = day;}void display() {std::cout << _year << "-" << _month << "-" << _day << std::endl;}private:int _year;int _month;int _day;
};

通过这个构造函数,创建对象时可以直接设置日期信息:

Date today(2024, 5, 28); // 调用构造函数
today.display(); // 输出: 2024-5-28
2.2 构造函数的特性

构造函数具有以下特性:

  1. 函数名与类名相同
  2. 无返回值
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载
示例代码:构造函数重载
class Date {
public:// 默认构造函数Date() : _year(0), _month(0), _day(0) {}// 带参数的构造函数Date(int year, int month, int day) : _year(year), _month(month), _day(day) {}void display() {std::cout << _year << "-" << _month << "-" << _day << std::endl;}private:int _year;int _month;int _day;
};
使用构造函数
Date defaultDate; // 调用默认构造函数
Date specificDate(2024, 5, 28); // 调用带参数的构造函数defaultDate.display(); // 输出: 0-0-0
specificDate.display(); // 输出: 2024-5-28
编译器生成的默认构造函数

如果没有显式定义构造函数,编译器会自动生成一个无参的默认构造函数。这个默认构造函数对内置类型成员变量不进行初始化,而对自定义类型成员变量会调用它们的默认构造函数。

class MyClass {
public:int a; // 内置类型,不会初始化std::string b; // 自定义类型,会调用其默认构造函数
};int main() {MyClass obj;std::cout << "a: " << obj.a << ", b: " << obj.b << std::endl; // a: 随机值, b: 空字符串return 0;
}
C++11中的改进

C++11允许在类定义时为内置类型成员变量提供默认值:

class MyClass {
public:int a = 0; // 内置类型,提供默认值std::string b; // 自定义类型
};int main() {MyClass obj;std::cout << "a: " << obj.a << ", b: " << obj.b << std::endl; // a: 0, b: 空字符串return 0;
}
总结

构造函数是用于初始化对象的特殊成员函数,其名称与类名相同且无返回值。构造函数可以重载,使得对象在不同的情况下被初始化。如果没有定义构造函数,编译器会生成一个默认的构造函数,但它对内置类型成员变量不进行初始化。C++11引入了在类定义时为内置类型成员变量提供默认值的功能,从而增强了默认构造函数的实用性。

3.析构函数详解

析构函数是C++中的一个重要概念,它使对象在销毁时能自动清理资源。以下是对析构函数的详细解释和代码示例,帮助初学者深入理解其原理和使用方法。

3.1 析构函数的概念

析构函数与构造函数功能相反,不是完成对对象本身的销毁,而是用于清理对象中的资源。当对象的生命周期结束时,C++编译器会自动调用析构函数。

示例类:Date

假设我们有一个 Date 类,不需要特别的资源管理,因此可以使用编译器生成的默认析构函数。

class Date {
public:Date(int year, int month, int day) : _year(year), _month(month), _day(day) {}void display() {std::cout << _year << "-" << _month << "-" << _day << std::endl;}~Date() {// 编译器会自动调用这个析构函数std::cout << "Date对象被销毁: " << _year << "-" << _month << "-" << _day << std::endl;}private:int _year;int _month;int _day;
};

通过这个析构函数,可以在对象销毁时自动打印一条消息:

int main() {Date today(2024, 5, 28);today.display();return 0;
}
// 输出:
// 2024-5-28
// Date对象被销毁: 2024-5-28
3.2 析构函数的特性

析构函数具有以下特性:

  1. 析构函数名是在类名前加上字符 ~
  2. 无参数,无返回值类型
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。析构函数不能重载。
  4. 对象生命周期结束时,C++编译系统自动调用析构函数
示例代码:编译器自动生成的析构函数
class MyClass {
public:MyClass() {std::cout << "MyClass对象创建" << std::endl;}~MyClass() {std::cout << "MyClass对象销毁" << std::endl;}
};int main() {MyClass obj;return 0;
}
// 输出:
// MyClass对象创建
// MyClass对象销毁

在上述代码中,当对象 obj 的生命周期结束时,编译器会自动调用析构函数。

资源管理示例:Stack类

当类中有资源需要管理时,例如动态内存,必须显式定义析构函数以防止资源泄漏。

class Stack {
public:Stack(int size) {_size = size;_data = new int[size]; // 动态分配内存std::cout << "Stack对象创建,分配内存" << std::endl;}~Stack() {delete[] _data; // 释放内存std::cout << "Stack对象销毁,释放内存" << std::endl;}private:int _size;int* _data;
};int main() {Stack stack(10);return 0;
}
// 输出:
// Stack对象创建,分配内存
// Stack对象销毁,释放内存
总结

析构函数是用于清理对象资源的特殊成员函数,其名称是在类名前加上字符 ~,且无参数和返回值。一个类只能有一个析构函数,不能重载。当对象的生命周期结束时,C++编译器会自动调用析构函数。对于没有资源需要管理的类,可以使用编译器生成的默认析构函数;对于需要管理资源的类,必须显式定义析构函数以防止资源泄漏。

4.拷贝构造函数详解

拷贝构造函数允许创建一个与已存在对象完全相同的新对象。以下是对拷贝构造函数的详细解释和代码示例,帮助初学者深入理解其原理和使用方法。

4.1 拷贝构造函数的概念

在C++中,拷贝构造函数是一个特殊的构造函数,用于创建一个与已有对象相同的新对象。它的参数是对本类类型对象的引用,通常用 const 修饰。

示例类:Date

假设我们有一个 Date 类,通过拷贝构造函数可以创建一个与已存在对象相同的新对象。

class Date {
public:Date(int year, int month, int day) : _year(year), _month(month), _day(day) {}// 拷贝构造函数Date(const Date& other) : _year(other._year), _month(other._month), _day(other._day) {std::cout << "调用拷贝构造函数" << std::endl;}void display() const {std::cout << _year << "-" << _month << "-" << _day << std::endl;}private:int _year;int _month;int _day;
};int main() {Date date1(2024, 5, 28);Date date2 = date1; // 调用拷贝构造函数date2.display();return 0;
}
// 输出:
// 调用拷贝构造函数
// 2024-5-28
4.2 拷贝构造函数的特征

拷贝构造函数具有以下特征:

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用。使用传值方式编译器会报错,因为会引发无穷递归调用。
  3. 若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数按内存存储字节序进行拷贝,这种拷贝叫做浅拷贝或值拷贝。内置类型按字节方式直接拷贝,自定义类型调用其拷贝构造函数完成拷贝。
浅拷贝与深拷贝
  • 浅拷贝:仅拷贝对象中的值,不考虑资源的深层次复制。
  • 深拷贝:不仅拷贝对象中的值,还对对象中涉及的资源进行深层次复制。
示例代码:浅拷贝与深拷贝
class Stack {
public:Stack(int size) : _size(size), _data(new int[size]) {std::cout << "Stack对象创建,分配内存" << std::endl;}// 拷贝构造函数实现深拷贝Stack(const Stack& other) : _size(other._size), _data(new int[other._size]) {std::copy(other._data, other._data + other._size, _data);std::cout << "调用拷贝构造函数,进行深拷贝" << std::endl;}~Stack() {delete[] _data;std::cout << "Stack对象销毁,释放内存" << std::endl;}private:int _size;int* _data;
};int main() {Stack stack1(10);Stack stack2 = stack1; // 调用拷贝构造函数return 0;
}
// 输出:
// Stack对象创建,分配内存
// 调用拷贝构造函数,进行深拷贝
// Stack对象销毁,释放内存
// Stack对象销毁,释放内存
拷贝构造函数的典型调用场景
  1. 使用已存在对象创建新对象
  2. 函数参数类型为类类型对象
  3. 函数返回值类型为类类型对象

为了提高程序效率,一般对象传参时尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

总结

拷贝构造函数是用于创建一个与已有对象相同的新对象的特殊构造函数。它的参数是对本类类型对象的引用,且无返回值。若未显式定义,编译器会生成默认的拷贝构造函数,对内置类型进行浅拷贝,对自定义类型调用其拷贝构造函数完成拷贝。对于涉及资源管理的类,显式定义拷贝构造函数以实现深拷贝是必要的,以防止资源泄漏。

5.赋值运算符重载详解

赋值运算符重载是C++中运算符重载的一种形式,它允许我们自定义类对象之间的赋值行为。以下是对赋值运算符重载的详细解释和代码示例,帮助初学者深入理解其原理和使用方法。

5.1 运算符重载概述

运算符重载是C++引入的一种机制,用于增强代码的可读性。运算符重载的函数具有特殊的名字,并且具有返回值类型、函数名字以及参数列表,其返回值类型和参数列表与普通的函数类似。函数名字为关键字 operator 后面接需要重载的运算符符号。

示例:运算符重载函数原型
5.2 赋值运算符重载

赋值运算符重载是一种常见的运算符重载形式,用于定义类对象之间的赋值操作。

赋值运算符重载格式
  • 参数类型const T&,传递引用可以提高传参效率。
  • 返回值类型T&,返回引用可以提高返回效率,并支持连续赋值。
  • 检测是否自己给自己赋值
  • 返回*this:符合连续赋值的含义。
示例类:Stack

假设我们有一个 Stack 类,通过赋值运算符重载可以定义对象之间的赋值操作。

class Stack {
public:Stack(int size) : _size(size), _data(new int[size]) {std::cout << "Stack对象创建,分配内存" << std::endl;}// 拷贝构造函数实现深拷贝Stack(const Stack& other) : _size(other._size), _data(new int[other._size]) {std::copy(other._data, other._data + other._size, _data);std::cout << "调用拷贝构造函数,进行深拷贝" << std::endl;}// 赋值运算符重载Stack& operator=(const Stack& other) {if (this == &other) {return *this; // 检测自我赋值}delete[] _data; // 释放旧内存_size = other._size;_data = new int[_size];std::copy(other._data, other._data + _size, _data);std::cout << "调用赋值运算符重载,进行深拷贝" << std::endl;return *this; // 支持连续赋值}~Stack() {delete[] _data;std::cout << "Stack对象销毁,释放内存" << std::endl;}private:int _size;int* _data;
};int main() {Stack stack1(10);Stack stack2(5);stack2 = stack1; // 调用赋值运算符重载return 0;
}
// 输出:
// Stack对象创建,分配内存
// Stack对象创建,分配内存
// Stack对象销毁,释放内存
// 调用赋值运算符重载,进行深拷贝
// Stack对象销毁,释放内存
赋值运算符重载的注意事项
  1. 赋值运算符只能重载成类的成员函数,不能重载成全局函数。原因是赋值运算符如果不显式实现,编译器会生成一个默认的。如果在类外实现一个全局的赋值运算符重载,会与编译器生成的默认赋值运算符重载冲突。
  2. 用户没有显式实现时,编译器会生成默认的赋值运算符重载,以值的方式逐字节拷贝。对于内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。
  3. 如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理,则必须实现
前置++和后置++重载

前置和后置自增运算符也可以重载。它们分别表示在变量本身修改之前和之后返回值。

示例代码:前置和后置自增运算符重载
class Counter {
public:Counter(int value = 0) : _value(value) {}// 前置++Counter& operator++() {++_value;return *this;}// 后置++Counter operator++(int) {Counter temp = *this;++_value;return temp;}void display() const {std::cout << "Counter: " << _value << std::endl;}private:int _value;
};int main() {Counter c(5);++c; // 前置++c.display(); // Counter: 6c++; // 后置++c.display(); // Counter: 7return 0;
}
总结

赋值运算符重载允许自定义类对象之间的赋值行为。它的参数类型通常是 const T&,返回值类型是 T&,并且需要检测自我赋值和返回 *this 以支持连续赋值。赋值运算符只能重载成类的成员函数,并且如果类涉及资源管理,则必须显式实现赋值运算符重载。前置和后置自增运算符也可以重载,以实现不同的自增行为。

6.日期类的实现

构造函数、拷贝构造函数、赋值运算符重载、析构函数以及基本的成员函数,用于表示和操作日期。

1. 定义Date类

首先,我们定义类的成员变量和基本的构造函数。

#include <iostream>class Date {
public:// 带参数的构造函数Date(int year, int month, int day) : _year(year), _month(month), _day(day) {std::cout << "调用带参数的构造函数" << std::endl;}// 默认构造函数Date() : _year(0), _month(0), _day(0) {std::cout << "调用默认构造函数" << std::endl;}// 拷贝构造函数Date(const Date& other) : _year(other._year), _month(other._month), _day(other._day) {std::cout << "调用拷贝构造函数" << std::endl;}// 赋值运算符重载Date& operator=(const Date& other) {if (this != &other) { // 检测自我赋值_year = other._year;_month = other._month;_day = other._day;std::cout << "调用赋值运算符重载" << std::endl;}return *this; // 支持连续赋值}// 析构函数~Date() {std::cout << "调用析构函数" << std::endl;}// 显示日期void display() const {std::cout << _year << "-" << _month << "-" << _day << std::endl;}private:int _year;int _month;int _day;
};int main() {// 创建日期对象并显示Date date1(2024, 5, 28);date1.display();// 使用拷贝构造函数创建新对象并显示Date date2 = date1;date2.display();// 使用赋值运算符重载并显示Date date3;date3 = date1;date3.display();return 0;
}

2. 详细解析每个部分

2.1 构造函数

构造函数用于初始化对象的成员变量。带参数的构造函数可以接受初始化参数,而默认构造函数则不接受参数。

// 带参数的构造函数
Date(int year, int month, int day) : _year(year), _month(month), _day(day) {std::cout << "调用带参数的构造函数" << std::endl;
}// 默认构造函数
Date() : _year(0), _month(0), _day(0) {std::cout << "调用默认构造函数" << std::endl;
}

当我们创建对象时,构造函数会被调用。例如:

Date date1(2024, 5, 28); // 调用带参数的构造函数
Date date3; // 调用默认构造函数
2.2 拷贝构造函数

拷贝构造函数用于创建一个新的对象作为已有对象的副本。它接受一个常量引用作为参数。

// 拷贝构造函数
Date(const Date& other) : _year(other._year), _month(other._month), _day(other._day) {std::cout << "调用拷贝构造函数" << std::endl;
}

当我们用一个已有对象初始化新对象时,拷贝构造函数会被调用。例如:

Date date2 = date1; // 调用拷贝构造函数
2.3 赋值运算符重载

赋值运算符重载用于定义对象之间的赋值操作。它返回一个对当前对象的引用,以支持连续赋值。

// 赋值运算符重载
Date& operator=(const Date& other) {if (this != &other) { // 检测自我赋值_year = other._year;_month = other._month;_day = other._day;std::cout << "调用赋值运算符重载" << std::endl;}return *this; // 支持连续赋值
}

当我们将一个对象赋值给另一个对象时,赋值运算符重载会被调用。例如:

date3 = date1; // 调用赋值运算符重载
2.4 析构函数

析构函数用于在对象生命周期结束时清理资源。

// 析构函数
~Date() {std::cout << "调用析构函数" << std::endl;
}

当对象超出其作用域时,析构函数会被调用。例如:

{Date tempDate; // 创建临时对象
} // tempDate 超出作用域,调用析构函数
2.5 显示日期

display函数用于输出日期。

// 显示日期
void display() const {std::cout << _year << "-" << _month << "-" << _day << std::endl;
}

运行上面的代码,将会输出以下内容:

调用带参数的构造函数
2024-5-28
调用拷贝构造函数
2024-5-28
调用默认构造函数
调用赋值运算符重载
2024-5-28
调用析构函数
调用析构函数
调用析构函数

7.深度剖析C++中的const成员函数

const成员函数是指被const修饰的成员函数,这种修饰实际作用于该成员函数的隐含this指针,表明在该成员函数中不能对类的任何成员进行修改。通过以下问题的解答,我们可以深入理解const成员函数的行为。

问题1: const对象可以调用非const成员函数吗?

不可以。因为非const成员函数可能会修改对象的状态,而const对象保证其状态不会被改变。

问题2: 非const对象可以调用const成员函数吗?

可以。const成员函数不会修改对象的状态,因此非const对象可以调用它。

问题3: const成员函数内可以调用其它的非const成员函数吗?

不可以。因为非const成员函数可能会修改对象的状态,而在const成员函数内不能修改对象的状态。

问题4: 非const成员函数内可以调用其它的const成员函数吗?

可以。非const成员函数可以调用const成员函数,因为const成员函数不会修改对象的状态。

示例代码

下面我们通过一个示例来说明这些概念。

#include <iostream>class MyClass {
public:// 构造函数MyClass(int value) : _value(value) {}// 非const成员函数void setValue(int value) {_value = value;}// const成员函数int getValue() const {return _value;}// 非const成员函数调用const成员函数void printValue() {std::cout << "Value: " << getValue() << std::endl; // 调用const成员函数}// const成员函数尝试调用非const成员函数void trySetValue(int value) const {// setValue(value); // 错误:const成员函数不能调用非const成员函数}private:int _value;
};int main() {MyClass obj(42);// 非const对象可以调用非const成员函数obj.setValue(100);// 非const对象可以调用const成员函数std::cout << "Value: " << obj.getValue() << std::endl;// const对象不能调用非const成员函数const MyClass constObj(42);// constObj.setValue(100); // 错误:const对象不能调用非const成员函数// const对象可以调用const成员函数std::cout << "Value: " << constObj.getValue() << std::endl;return 0;
}

解释

构造函数和成员变量
MyClass(int value) : _value(value) {}

构造函数初始化成员变量_value

const成员函数
void setValue(int value) {_value = value;
}

const成员函数可以修改成员变量。

const成员函数
int getValue() const {return _value;
}

const成员函数不能修改成员变量。

const成员函数调用const成员函数
void printValue() {std::cout << "Value: " << getValue() << std::endl;
}

const成员函数可以调用const成员函数。

const成员函数尝试调用非const成员函数
void trySetValue(int value) const {// setValue(value); // 错误:const成员函数不能调用非const成员函数
}

const成员函数不能调用非const成员函数。

main函数示例
int main() {MyClass obj(42);// 非const对象可以调用非const成员函数obj.setValue(100);// 非const对象可以调用const成员函数std::cout << "Value: " << obj.getValue() << std::endl;// const对象不能调用非const成员函数const MyClass constObj(42);// constObj.setValue(100); // 错误:const对象不能调用非const成员函数// const对象可以调用const成员函数std::cout << "Value: " << constObj.getValue() << std::endl;return 0;
}

8.取地址及const取地址操作符重载

在C++中,取地址运算符(&)和const取地址运算符是两个默认成员函数,编译器会自动生成这些函数。通常情况下,我们不需要重新定义它们。但在某些特殊情况下,例如我们希望控制取地址运算符的行为,让它返回特定的内容时,才需要重载它们。下面我们将详细解释这些概念,并通过代码示例帮助理解。

1. 取地址运算符(&

取地址运算符用于获取对象的内存地址。在大多数情况下,编译器会生成默认的取地址运算符。但有时候我们希望取地址运算符返回特定的内容,这时就需要重载它。

2. const取地址运算符

const取地址运算符类似于取地址运算符,但它只能在const对象上调用。编译器也会生成默认的const取地址运算符,我们可以根据需要重载它。

示例代码

为了帮助理解,我们将实现一个示例类 MyClass,并重载其取地址运算符和const取地址运算符。

#include <iostream>class MyClass {
public:MyClass(int value) : _value(value) {}// 重载取地址运算符int* operator&() {std::cout << "调用重载的取地址运算符" << std::endl;return &_value;}// 重载const取地址运算符const int* operator&() const {std::cout << "调用重载的const取地址运算符" << std::endl;return &_value;}void display() const {std::cout << "Value: " << _value << std::endl;}private:int _value;
};int main() {MyClass obj(42);const MyClass constObj(100);obj.display();constObj.display();// 调用重载的取地址运算符int* addr = &obj;std::cout << "非const对象地址指向的值: " << *addr << std::endl;// 调用重载的const取地址运算符const int* constAddr = &constObj;std::cout << "const对象地址指向的值: " << *constAddr << std::endl;return 0;
}

代码解释

  1. 构造函数:用于初始化对象的成员变量 _value
  2. 重载取地址运算符:返回对象的 _value 的地址,并打印一条信息。
    int* operator&() {std::cout << "调用重载的取地址运算符" << std::endl;return &_value;
    }
    
  3. 重载const取地址运算符:返回const对象的 _value 的地址,并打印一条信息。
    const int* operator&() const {std::cout << "调用重载的const取地址运算符" << std::endl;return &_value;
    }
    
  4. 显示成员函数:显示对象的 _value
    void display() const {std::cout << "Value: " << _value << std::endl;
    }
    
  5. main函数:创建非const对象和const对象,调用重载的取地址运算符和const取地址运算符。
    int main() {MyClass obj(42);const MyClass constObj(100);obj.display();constObj.display();// 调用重载的取地址运算符int* addr = &obj;std::cout << "非const对象地址指向的值: " << *addr << std::endl;// 调用重载的const取地址运算符const int* constAddr = &constObj;std::cout << "const对象地址指向的值: " << *constAddr << std::endl;return 0;
    }
    
    运行示例

    运行上面的代码,将会输出以下内容:

    Value: 42
    Value: 100
    调用重载的取地址运算符
    非const对象地址指向的值: 42
    调用重载的const取地址运算符
    const对象地址指向的值: 100
    

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

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

相关文章

Docker部署后的中文乱码问题

本地和服务器上面生成图片文字多没有乱码&#xff0c;但是服务部署到docker上面就开始出现乱码。排查了一下发现是docker上缺少相应的中文字体&#xff0c;添加字体即可解决。 1.在网站上找到相关资源并下载字体-字体下载-字体下载大全-字体免费下载|字体下载 2.上传到服务器 …

8D和FMEA的关系是什么?——FMEA软件

免费试用FMEA软件-免费版-SunFMEA 在质量管理领域中&#xff0c;8D和FMEA是两个非常重要的工具。它们各自有着独特的作用&#xff0c;但同时又存在着紧密的联系。本文旨在深入探讨8D和FMEA之间的关系&#xff0c;以及它们如何协同工作以提高产品质量和客户满意度。 8D&#x…

电子商务商城B2B2C:JAVA实现的商家间直播带货商城系统概览

电子商务商城&#xff1a;构建全行业全渠道的一体化SaaS解决方案 在数字化转型的浪潮中&#xff0c;企业对于高效、集成的管理系统的需求日益增长。电子商务商城的SaaS云平台应运而生&#xff0c;它旨在为各行各业提供全面的一体化解决方案&#xff0c;无论是门店经营的区域化…

UE5 Cesium2 最新使用地理配准子关卡构造全球场景

参考官方最新教程&#xff1a;Building Global Scenes with Georeferenced Sublevels – Cesium 创建持久关卡&#xff08;主关卡&#xff09; 这里一般包含DynamicPawn、CesiumSunSky 和 Cesium World Terrain 全球场景通用的对象。子关卡的创立&#xff0c;官方教程分为了两…

低代码与人工智能:革新智能客服系统的高效之道

引言 在当前数字化和智能化浪潮的推动下&#xff0c;企业对智能客服系统的需求呈现显著增长。随着客户期望的不断提升&#xff0c;企业需要更加高效、智能和个性化的客户服务解决方案。传统的人工客服方式不仅成本高昂&#xff0c;且难以满足大规模、多样化的客户需求。而智能客…

如何远程访问Redis?

远程访问Redis是一种常见的需求&#xff0c;特别是在分布式系统或跨地域网络中。通过远程访问&#xff0c;我们可以轻松地对远程的Redis数据库进行操作和管理。 天联保障数据安全 对于远程访问Redis的安全性问题&#xff0c;我们可以借助天联来保障数据的安全。天联是一种基于…

免费无限换脸,火了,图片/视频/直播都行!

最强换脸AI工具Facefusion软件在近期更新到了2.6.0版本&#xff0c;带来了一系列的更新和改进&#xff0c;今天为大家分享一下最新的整合包。 Facefusion2.6.0版本介绍 FaceFusion不仅仅是一款换脸软件&#xff0c;它更是一个多功能的数字人和实时直播助手&#xff0c;真正开启…

python Windows电脑设置定时启动程序,定时运行代码

Windows设置定时 一&#xff0c;新建文件txt, .txt改为.bat 路径填exe的路径D:\test\main.py 如下是启动exe,如果运行python代码则写入如&#xff1a;python D:\test\main.py 二&#xff0c;搜索计算机管理 三&#xff0c;点击创建基本任务 填写任意名称 选择什么时候开始…

Element-Plus中表格及分页功能

导入Element-Plus 具体步骤如下&#xff1a;&#xff08;内容参照官网&#xff1a;安装 | Element Plus&#xff09; # 选择一个你喜欢的包管理器# NPM $ npm install element-plus --save# Yarn $ yarn add element-plus# pnpm $ pnpm install element-plus 安装完成后即可…

实现按块复制元素的进阶技巧

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、按块复制元素的重要性 二、使用LED模块创建数组并复制 三、实现按块复制的具体步骤 四…

群晖NAS使用Docker部署WPS Office结 合内网穿透实现远程编辑本地文档

文章目录 1. 拉取WPS Office镜像2. 运行WPS Office镜像容器3. 本地访问WPS Office4. 群晖安装Cpolar5. 配置WPS Office远程地址6. 远程访问WPS Office小结 7. 固定公网地址 wps-office是一个在Linux服务器上部署WPS Office的镜像。它基于WPS Office的Linux版本&#xff0c;通过…

基于微信小程序+ JAVA后端实现的【微信小程序跑腿平台】设计与实现 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 《微信小程序跑腿平台的设计与实现》 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; Java, SSM框架数据库&#xff1a; MySQL前端技术&#xff1a; 微信小程序, HTML…&#xff08;其它相关技术&#xff09; …

工作软件新宠儿

想要让你的工作效率飞起来吗&#xff1f;&#x1f440; 是时候告别那些大众化的工作软件啦&#xff01;今天&#xff0c;我要给大家种草几款不常见的但超级实用的工作软件&#x1f331;&#xff0c;保证让你事半功倍哦&#xff01;&#x1f31f; 1️⃣ 亿可达 它是一款自动化…

【NumPy】深入理解NumPy的cov函数:计算协方差矩阵的完整指南

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

ADC模数转换器的简介及参数详解

ADC全称是Analog-to-Digital Converter模数转换器&#xff0c;一般我们把模拟信号(Analog signal) 用A来进行简写&#xff0c;数字信号(digital signal) 用D来表示。是用于将模拟形式的连续信号转换为数字形式的离散信号的一类设备。 今天我们主要说ADC的参数&#xff0c;我们把…

​你见过哪些不过度设计的优秀APP?​

优联前端https://ufrontend.com/ 提供一站式企业前端解决方案 “每日故宫”是一款以故宫博物院丰富的藏品为基础&#xff0c;结合日历形式展示每日精选藏品的移动应用。通过这款应用&#xff0c;用户可以随时随地欣赏到故宫的珍贵藏品&#xff0c;感受中华五千年文化的魅力。…

算法工程师需要学习C++的哪些知识?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;以下是算法工程师需要学习的一些…

配餐中的红酒温度控制与口感体验

在红酒配餐中&#xff0c;温度控制是影响口感体验的重要因素之一。合适的温度可以释放红酒的香气和风味&#xff0c;使酒体更加圆润和丰富。云仓酒庄雷盛红酒以其卓着的品质和与众不同的口感&#xff0c;成为了红酒爱好者们的首要选择品牌。下面将介绍如何通过温度控制提升红酒…

简单微信企业群消息推送接口

群管理 群发送接口 POST: JSONURL http://localhost:65029/m/wxapi/sendwxmsg{ "nr":"试", --消息 "at":"wxid_y0k4dv0xcav622,wxid_y0k4dv0xcav622",--群wxid "key":"F98F354F1671A2D21BC78C76B95E96EB",--群k…

重庆耶非凡科技有限公司有选品师项目培训吗?

在当今科技飞速发展的时代&#xff0c;各种科技公司如雨后春笋般涌现&#xff0c;它们在不同领域发挥着重要作用。其中&#xff0c;重庆耶非凡科技有限公司以其独特的业务模式和专业服务&#xff0c;在业界赢得了良好的口碑。那么&#xff0c;重庆耶非凡科技有限公司究竟是做什…