讲师中心 微信公众号

工具推荐

视频效率加速
Seko
Seko

AI短剧一键生成成片

Laper
Laper

剧本策划到成片协作

updream

一键生成高质量推广成片

AniShort
AniShort

AI短剧协同制作平台

委托构造函数怎样工作 构造函数代码复用技巧

梦涛小哥_7997

梦涛小哥_7997

发布时间:2025-08-16 19:18:02

|

470人浏览过

|

来源于php中文网

原创

委托构造函数通过让一个构造函数调用同类的另一个构造函数,实现初始化逻辑复用,减少代码冗余。其语法为在构造函数初始化列表中使用 : this(...),被委托的构造函数先执行,完成后才执行委托构造函数体。它适用于多个构造函数共享通用初始化逻辑的场景,如设置默认值、资源分配等,能集中维护初始化代码,降低出错风险。但需注意:不能同时委托构造函数和调用基类构造函数;禁止循环委托;成员初始化应集中在被委托的构造函数中;委托不替代基类构造函数调用。该机制提升代码整洁性与可维护性,是C++11引入的重要特性。

委托构造函数怎样工作 构造函数代码复用技巧

委托构造函数,简单来说,就是让一个构造函数去调用同一个类的另一个构造函数。这主要是为了解决构造函数内部初始化逻辑重复的问题,能有效减少代码冗余,让你的类初始化变得更简洁、更易维护。当你有多种方式创建对象,但它们又共享大部分初始化步骤时,这技巧就显得尤为实用。

委托构造函数的工作机制其实挺直观的。当你定义一个构造函数,并在其初始化列表中使用

: this(...)
来调用另一个构造函数时,编译器会确保被委托的构造函数先完全执行完毕,包括其成员初始化和构造函数体。只有当被委托的构造函数完成后,委托构造函数自身的函数体才会开始执行。这就像是把初始化的大部分“脏活累活”都甩给了一个专门的“主”构造函数,其他构造函数只需要负责把参数整理好,然后丢给它就行了。这样一来,那些通用的初始化代码就只需要写一次,放在那个被委托的构造函数里,大大降低了出错的概率,也让代码看起来清爽多了。

为什么在C++中我们需要使用委托构造函数?

在C++编程实践中,我们经常会遇到一个类有多个构造函数的情况。比如,你可能有一个默认构造函数,一个接受少量参数的构造函数,还有一个接受所有参数的构造函数。如果这些构造函数都需要对成员变量进行一系列共同的初始化操作,比如设置默认值、分配资源或者进行一些复杂的校验,那么这些初始化逻辑很可能会被复制粘贴到每一个构造函数里。这简直是维护者的噩梦。

想象一下,如果某个初始化逻辑需要修改,你得逐一检查并修改所有相关的构造函数,这不仅效率低下,而且极易遗漏,从而引入潜在的bug。代码重复是软件开发中的大忌,它直接增加了代码的复杂性、维护成本和出错的可能性。委托构造函数恰好就是为了解决这个痛点而生的。它提供了一种优雅的方式,把所有共享的初始化逻辑集中到一个“核心”构造函数中,其他构造函数通过委托调用它,从而实现代码的复用。这不仅仅是语法上的便利,更是设计思想上的进步,它强制你思考如何更好地组织和抽象你的初始化流程。

委托构造函数的语法与实际代码示例

委托构造函数的语法其实非常简洁,它出现在构造函数的初始化列表中。以C++为例,它的形式是

ConstructorName(...) : this(arguments_for_delegated_constructor) { /* delegating constructor's own logic */ }
。

我们来看一个简单的

Person
类例子:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
#include <iostream>
#include <string>

class Person {
private:
    std::string name;
    int age;
    std::string city;

    // 核心构造函数,负责所有成员的初始化
    Person(const std::string& n, int a, const std::string& c) : name(n), age(a), city(c) {
        std::cout << "核心构造函数执行: " << name << ", " << age << ", " << city << std::endl;
        // 任何通用的初始化逻辑都放这里
        if (age < 0) {
            age = 0; // 确保年龄非负
        }
    }

public:
    // 委托构造函数1: 只提供姓名和年龄,城市默认
    Person(const std::string& n, int a) : this(n, a, "未知城市") {
        std::cout << "委托构造函数 (姓名, 年龄) 执行完毕." << std::endl;
    }

    // 委托构造函数2: 只提供姓名,年龄和城市默认
    Person(const std::string& n) : this(n, 18) { // 委托给 (姓名, 年龄) 构造函数
        std::cout << "委托构造函数 (姓名) 执行完毕." << std::endl;
    }

    // 委托构造函数3: 默认构造函数
    Person() : this("匿名", 18) { // 委托给 (姓名, 年龄) 构造函数
        std::cout << "委托构造函数 (默认) 执行完毕." << std::endl;
    }

    void display() const {
        std::cout << "姓名: " << name << ", 年龄: " << age << ", 城市: " << city << std::endl;
    }
};

int main() {
    std::cout << "--- 创建 p1 (完整参数) ---" << std::endl;
    Person p1("张三", 30, "北京"); // 直接调用核心构造函数
    p1.display();
    std::cout << std::endl;

    std::cout << "--- 创建 p2 (姓名, 年龄) ---" << std::endl;
    Person p2("李四", 25); // 调用委托构造函数 Person(const std::string& n, int a)
    p2.display();
    std::cout << std::endl;

    std::cout << "--- 创建 p3 (姓名) ---" << std::endl;
    Person p3("王五"); // 调用委托构造函数 Person(const std::string& n)
    p3.display();
    std::cout << std::endl;

    std::cout << "--- 创建 p4 (默认) ---" << std::endl;
    Person p4; // 调用委托构造函数 Person()
    p4.display();
    std::cout << std::endl;

    return 0;
}

运行上述代码,你会发现输出的顺序清晰地展示了委托的执行流程:先是核心构造函数被调用并完成初始化,然后才是委托构造函数自身的函数体执行。比如,当创建

p2("李四", 25)
时,你会看到 "核心构造函数执行" 的输出,然后才是 "委托构造函数 (姓名, 年龄) 执行完毕."。这正是我们想要的效果,确保了所有通用初始化逻辑的唯一执行点。

委托构造函数的限制与使用考量

虽然委托构造函数是代码复用的利器,但它也有一些固有的限制和需要注意的地方。理解这些能帮助你更好地运用它,避免一些不必要的坑。

一个很重要的点是,你不能在同一个构造函数的初始化列表中既调用基类构造函数又委托给同类的另一个构造函数。这是互斥的。如果你需要初始化基类部分,那么这个构造函数就不能再委托了,它得自己完成所有初始化工作,包括调用基类构造函数。这其实也很好理解,因为委托意味着把控制权交给了另一个构造函数,而基类构造函数的调用是当前构造函数必须直接完成的任务。

另一个限制是,委托构造函数不能形成循环委托。也就是说,A委托B,B不能再委托回A,或者A委托B,B委托C,C又委托回A。编译器会检测并阻止这种循环依赖,否则会导致无限递归。这和函数调用栈溢出的道理是类似的。

再者,委托构造函数在执行顺序上有一个微妙但关键的特性:被委托的构造函数会先于委托构造函数自身的成员初始化列表和函数体执行。这意味着,如果你在委托构造函数的成员初始化列表中尝试初始化某个成员,但这个成员又在被委托的构造函数中被初始化了,那么被委托的构造函数的初始化会覆盖掉委托构造函数初始化列表中的值。通常的做法是,将所有成员的初始化都交给那个“核心”或“最完整”的构造函数,其他委托构造函数则不进行成员初始化,只负责参数的转换和传递。

最后,委托构造函数主要用于同类内部的构造函数代码复用。它不是用来替代继承体系中基类构造函数调用的。对于基类的初始化,你仍然需要在派生类的构造函数初始化列表中显式调用基类构造函数。这是一个常见的误区,需要清晰区分。委托构造函数让你的类内部更整洁,而基类构造函数调用则关乎继承体系的正确构建。

热门AI工具

更多
UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

7007

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2888

2023.08.10

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

20

2026.11.12

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

20

2026.11.12

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

120

2026.11.06

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

100

2026.11.06

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

100

2026.11.06

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

80

2026.11.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn