当前位置: 首页 > news >正文

5、类的6个默认成员函数和特性--类的新功能

一、首先要了解构造函数6大类【不是特性】

1. 构造函数 (Constructor)

class MyClass {
public:
    // 默认构造函数
    MyClass() : data(0) {}
    
    // 带参数构造函数
    MyClass(int val) : data(val) {}
    
private:
    int data;
};

2. 析构函数 (Destructor)

class MyClass {
public:
    ~MyClass() {
        // 清理资源
    }
};

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

class MyClass {
public:
    // 拷贝构造函数
    MyClass(const MyClass& other) : data(other.data) {}
    
private:
    int data;
};
  • 拷贝构造函数的参数只有一个且必须使用引用传参,否则 使用传值方式会引发无穷递归调用
    • 这里的理解可能比较困难。你可以想象,你使用一个带参数的函数,就要先传参再使用函数。下图的Date(const Date d)参数是另一个新的函数const Date d ,为了获得这个const Date d ,就需要构造这个const Date d ,又要传入一个const Date d,反反复复就导致递归了。
  • 调用拷贝构造的方式是 MyClass new_object(old_object)或MyClass new_object = old_object的写法 。把旧对象的传入到新的对象里。
  • 其过程,如下图
    在这里插入图片描述
  • 在这里插入图片描述

4. 拷贝赋值函数 (Copy Assignment Operator)

class MyClass {
public:
    // 拷贝赋值运算符
    MyClass& operator=(const MyClass& other) {
        if (this != &other) {  // 防止自赋值
            data = other.data;
        }
        return *this;
    }
    
private:
    int data;
};
  • 那么如何区分拷贝构造和拷贝复制呢?
  • 如下图:
  • 在这里插入图片描述

5. 取地址重载函数 (Address-of Operator)

class MyClass {
public:
    // 取地址运算符重载
    MyClass* operator&() {
        return this;// 返回假地址
    }
};

6. const 取地址重载函数 (const Address-of Operator)

class MyClass {
public:
    // const 取地址运算符重载
    const MyClass* operator&() const {
        return this;// const同样返回假地址
    }
};

7、完整示例

#include <iostream>

class Example {
public:
    // 1. 构造函数
    Example() : data(0) { std::cout << "Default Constructor\n"; }
    Example(int d) : data(d) { std::cout << "Param Constructor\n"; }
    
    // 2. 析构函数
    ~Example() { std::cout << "Destructor\n"; }
    
    // 3. 拷贝构造函数
    Example(const Example& other) : data(other.data) {
        std::cout << "Copy Constructor\n";
    }
    
    // 4. 拷贝赋值函数
    Example& operator=(const Example& other) {
        std::cout << "Copy Assignment\n";
        if (this != &other) {
            data = other.data;
        }
        return *this;
    }
    
    // 5. 取地址重载
    Example* operator&() {
        std::cout << "Non-const Address-of\n";
        return this;
    }
    
    // 6. const取地址重载
    const Example* operator&() const {
        std::cout << "Const Address-of\n";
        return this;
    }
    
private:
    int data;
};

int main() {
    Example e1;          // 默认构造函数
    Example e2(10);      // 参数构造函数
    Example e3 = e2;     // 拷贝构造函数
    e1 = e3;             // 拷贝赋值函数
    
    Example* p1 = &e1;   // 非const取地址
    const Example* p2 = &e2;  // const取地址
    
    return 0;
}

关键点说明:

  1. 构造函数:对象创建时调用,可以有多个重载版本
  2. 析构函数:对象销毁时调用,用于资源清理
  3. 拷贝构造函数:用已有对象创建新对象时调用
  4. 拷贝赋值函数:已有对象间赋值时调用
  5. 取地址重载:通常不需要重载,除非需要特殊行为
  6. const版本:为const对象提供操作

二、类的新功能【11特性】

1、default

  • 强制生成默认函数的关键字default
  • 也就是运行默认实现
class MyClass {
public:
    MyClass() = default;                      // 默认构造函数
    MyClass(const MyClass&) = default;       // 默认拷贝构造
    MyClass& operator=(const MyClass&) = default;  // 默认拷贝赋值
    ~MyClass() = default;                    // 默认析构函数
};

2、delete

  • 禁止生成默认函数的关键字delete
  • 也就是禁止默认实现
  • 例如,要让一个类不能被拷贝,可以用=delete修饰将该类的拷贝构造和拷贝赋值。
class CopyBan
{
public:
	CopyBan()
	{}
private:
	CopyBan(const CopyBan&) = delete;
	CopyBan& operator=(const CopyBan&) = delete;
};

3、override

  • override修饰子类的虚函数。
  • 子类继承父类虚函数时,子类是否正确重写了虚函数。没有就会编译错误。
class Base {
public:
    virtual void foo() { std::cout << "Base::foo\n"; }
    virtual void bar() const { std::cout << "Base::bar\n"; }
};

class Derived : public Base {
public:
    void foo() override {  // 正确:重写 Base::foo
        std::cout << "Derived::foo\n";
    }
    // void bar() override { ... }  // 错误!签名不匹配(缺少 const)
    void bar() const override {     // 正确:重写 Base::bar
        std::cout << "Derived::bar\n";
    }
};

4、final

4.1、修饰类

  • 被final修饰的类叫做最终类最终类无法被继承
class NoHeritage final //被final修饰,该类不能再被继承
{
	//...
};

4.2、修饰虚函数

  • 表示该虚函数不能再被重写,如果子类继承后重写了该虚函数则编译报错。
class Base {
public:
    virtual void foo() final {  // 派生类不能重写 foo
        std::cout << "Base::foo\n";
    }
};

class Derived : public Base {
public:
    // void foo() override { ... }  // 错误!foo 是 final
};

相关文章:

  • 高级java每日一道面试题-2025年3月14日-微服务篇[Eureka篇]-Eureka如何保证高可用性?
  • freecad手动装插件 add on
  • 最大数字(java)(DFS实现)
  • AMD机密计算虚拟机介绍
  • ubuntu系统安装docker
  • 天梯赛 L2-022 重排链表
  • 自顶向下学习K8S--部署Agones
  • Lua 数组
  • 平安证券 NoETL 指标平台实践:统一数据口径,驱动高效经营分析与智能决策
  • Ubuntu 使用终端手动连接无线网络(wlan0)完整流程 + 故障排查记录
  • Vue3.5 企业级管理系统实战(十一):全屏切换组件
  • 产生式系统的完整示例——医疗诊断系统(附python代码)
  • zookeeper部署教程
  • 如何自动化同义词并使用我们的 Synonyms API 进行上传
  • java项目之基于ssm的亚盛汽车配件销售业绩管理系统(源码+文档)
  • 【每日算法】Day 11-1:分治算法精讲——从归并排序到最近点对问题(C++实现)
  • [运维]Linux系统扩容磁盘空间-将未分配的空间进行整合分配
  • 规范Unity工程目录和脚本结构能有效提升开发效率、降低维护成本
  • FastBlock是一个专为全闪存场景设计的高性能分布式块存储系统
  • Pytroch搭建全连接神经网络识别MNIST手写数字数据集
  • 白玉兰奖征片综述丨海外剧创作趋势观察:跨界·融变·共生
  • 既是工具又是食物,可食用机器人开启舌尖上的新科技
  • 讲座预告|以危机为视角解读全球治理
  • 国家卫健委通报:吊销肖某医师执业证书,撤销董某莹四项证书
  • 丹麦外交大臣拉斯穆森将访华
  • 女孩患异食癖爱吃头发,一年后腹痛入院体内惊现“头发巨石”