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

C++ 语言特性10 - 委托构造函数

1:什么是委托构造函数?

        在C++中,委托构造函数(Delegating Constructor)是一种特殊的构造函数,它在构造函数的初始化列表中调用同一个类中的另一个构造函数,从而实现代码的复用。这种特性在C++11中引入。

class MyClass {
public:
    // 委托构造函数
    MyClass(int x, int y) : MyClass(x) {
        // 委托给另一个构造函数
    }
    
    // 被委托的构造函数
    MyClass(int x) {
        // 初始化代码
    }
};

2. 委托构造函数在什么场景中使用?

  • 代码复用: 当多个构造函数需要执行相同的初始化步骤时,可以使用委托构造函数来避免代码重复。

#include <iostream>
#include <string>

class Person {
public:
    Person() : Person("Unknown", 0) {
        std::cout << "Default constructor called\n";
    }
    
    Person(std::string name) : Person(name, 0) {
        std::cout << "Name constructor called\n";
    }
    
    Person(std::string name, int age) : name(name), age(age) {
        std::cout << "Full constructor called for " << name << std::endl;
    }

private:
    std::string name;
    int age;
};

int main() {
    Person p1;
    Person p2("Alice");
    Person p3("Bob", 30);
    return 0;
}
  • 链式委托: 一个构造函数可以委托给另一个构造函数,而后者又可以委托给下一个,形成一个委托链。

class Matrix {
public:
    Matrix() : Matrix(0, nullptr) {
        std::cout << "Default constructor called\n";
    }
    
    Matrix(size_t rows, size_t cols) : Matrix(rows, cols, new double*[rows]) {
        std::cout << "Size constructor called\n";
    }
    
    Matrix(size_t rows, size_t cols, double** data) : rows(rows), cols(cols), data(data) {
        std::cout << "Data constructor called\n";
    }

private:
    size_t rows;
    size_t cols;
    double** data;
};

int main() {
    Matrix mat;
    return 0;
}
  • 继承和覆盖: 在继承的类中,可以利用委托构造函数调用基类的构造函数,以确保正确的初始化。

class Base {
public:
    Base(int x) {
        std::cout << "Base constructor with int called\n";
    }
};

class Derived : public Base {
public:
    // 委托给基类的构造函数
    Derived(double x) : Base(static_cast<int>(x)) {
        std::cout << "Derived constructor with double called\n";
    }
};

int main() {
    Derived d(3.14);
    return 0;
}

3. 注意事项:

  • 委托目标的选择: 确保委托的目标构造函数是有效的,并且能够正确初始化对象。

#include <iostream>
#include <string>
#include <vector>

class Data {
public:
    // 正确的委托目标选择
    Data(const std::string& str) : Data(str.begin(), str.end()) {}
    
    // 正确的初始化列表
    Data(const char* begin, const char* end) {
        // 做一些初始化工作
        for (; begin != end; ++begin) {
            values.push_back(*begin);
        }
        std::cout << "Data initialized with " << values.size() << " elements." << std::endl;
    }

private:
    std::vector<char> values;
};

int main() {
    Data d("Hello");
    return 0;
}
  • 构造函数的递归调用: 避免构造函数之间的无限递归调用。

class RecursiveConstructor {
public:
    // 错误:递归调用自身
    RecursiveConstructor() : RecursiveConstructor(42) {}
    
    RecursiveConstructor(int) {
        std::cout << "Constructor called" << std::endl;
    }
};

int main() {
    // RecursiveConstructor rc; // 这将导致无限递归调用
    return 0;
}
  • 资源管理: 在委托构造函数中,确保资源被正确管理和释放。

#include <iostream>

class Resource {
public:
    // 委托构造函数正确地管理资源
    Resource(int id) : Resource(id, new int(id * 10)) {
        std::cout << "Resource ID: " << *data << std::endl;
    }
    
    // 被委托的构造函数
    Resource(int id, int* data) : id(id), data(data) {}
    
    ~Resource() {
        delete data;
    }

private:
    int id;
    int* data;
};

int main() {
    Resource res(1);
    return 0;
}

//在这个例子中,委托构造函数确保了资源(动态分配的整数)被正确地分配和初始化。
  • 异常安全: 委托构造函数需要考虑异常安全性,确保在抛出异常时对象处于一致的状态。

#include <iostream>
#include <string>

class ExceptionSafe {
public:
    // 委托构造函数
    ExceptionSafe(const std::string& str) : ExceptionSafe(str.begin(), str.end()) {
        // 做一些可能会抛出异常的操作
        if (str.empty()) {
            throw std::invalid_argument("String is empty");
        }
    }
    
    // 被委托的构造函数
    ExceptionSafe(const char* begin, const char* end) {
        // 做一些初始化工作
        try {
            for (; begin != end; ++begin) {
                values.push_back(*begin);
            }
        } catch (...) {
            // 异常发生时进行清理工作
            std::cout << "Exception caught during initialization." << std::endl;
            throw;
        }
        std::cout << "Data initialized with " << values.size() << " elements." << std::endl;
    }

private:
    std::vector<char> values;
};

int main() {
    try {
        ExceptionSafe es("Hello");
        ExceptionSafe esEmpty("");
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}


http://www.kler.cn/news/331461.html

相关文章:

  • QQ机器人搭建
  • iframe标签是做什么用的
  • 计算机毕业设计 Java酷听音乐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • map部分重点
  • <数据集>工程机械识别数据集<目标检测>
  • FBX福币历史重演,ETH可能会在第四季度出现熊市
  • mysql安装及使用·1
  • 计算机毕业设计Python抖音可视化 抖音大数据分析 抖音爬虫 抖音用户行为分析 抖音大数据 Hadoop Spark 数据仓库 推荐系统 机器学习 深度学习
  • [Unity Demo]从零开始制作空洞骑士Hollow Knight第十二集:制作完整地图和地图细节设置以及制作相机系统的跟随玩家和视角锁定功能
  • 在线JSON可视化工具--支持缩放
  • 华为云技术深度解析:以系统性创新加速智能化升级
  • map_set的使用
  • 【Windows】 C++实现 Socket 通讯
  • 行为型模式-策略模式详解
  • 【D3.js in Action 3 精译_025】3.4 让 D3 数据适应屏幕(中)—— 线性比例尺的用法
  • PASCAL VOC 2012数据集 20类物体,这些物体包括人、动物(如猫、狗、鸟等)、交通工具(如车、船、飞机等)以及家具(如椅子、桌子、沙发等)。
  • C++游戏开发深度解析
  • 滚雪球学Oracle[4.2讲]:PL/SQL基础语法
  • 在LabVIEW中如何读取EXCEL
  • Proxmox使用tc给虚拟机限速,实现不对等网速——浪浪云