news 2026/4/17 20:28:17

C++11新特性(十二)——委托构造函数和继承构造函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++11新特性(十二)——委托构造函数和继承构造函数

目录

1 委托构造函数

2 继承构造函数


1 委托构造函数

委托构造函数允许使用同一个类中的一个构造函数调用其他的构造函数,从而简化相关变量的初始化。下面通过一个例子说明:

class Test { public: Test() {}; Test(int max) { this->m_max = max > 0 ? max : 100; } Test(int max, int min) { this->m_max = max > 0 ? max : 100; // 冗余代码 this->m_min = min > 0 && min < max ? min : 1; } Test(int max, int min, int mid) { this->m_max = max > 0 ? max : 100; // 冗余代码 this->m_min = min > 0 && min < max ? min : 1; // 冗余代码 this->m_mid = mid < max && mid > min ? mid : 50; } public: int m_max; int m_min; int m_mid; }; int main() { Test t(90, 30, 60); cout << "min: " << t.m_min << ", middle: " << t.m_mid << ", max: " << t.m_max << endl; return 0; }

在上面三个重载的构造函数中都出现重复的代码,在 C++11 以前,我们会把重复的代码放到一个函数里,然后调用;在 C++11 以后,加入了委托构造,我们就可以轻松地完成代码的优化了

class Test { public: Test() {}; Test(int max) { this->m_max = max > 0 ? max : 100; } Test(int max, int min) : Test(max) { this->m_min = min > 0 && min < max ? min : 1; } Test(int max, int min, int mid) : Test(max,min) { this->m_mid = mid < max && mid > min ? mid : 50; } public: int m_max; int m_min; int m_mid; }; int main() { Test t(90, 30, 60); cout << "min: " << t.m_min << ", middle: " << t.m_mid << ", max: " << t.m_max << endl; return 0; }

修改完代码之后,冗余的代码全部都没有了,并且在一个构造函数中调用了其他的构造函数用于相关数据的初始化,相当于是一个链式调用。在使用委托构造函数的时候还需要注意一些几个问题

  • 这种链式的构造函数调用不能形成一个闭环,否则会在运行期间抛出异常
  • 如果要进行多层构造函数的链式调用,建议将构造函数的调用的写在初始列表中而不是函数体内部,否则编译器会提示形参的重复定义。
Test() {}; Test(int max) { this->m_max = max > 0 ? max : 100; } Test(int max, int min) { Test(max); //报错 this->m_min = min > 0 && min < max ? min : 1; } Test(int max, int min, int mid) { Test(max, min); //报错 this->m_mid = mid < max && mid > min ? mid : 50; }
  • 在初始化列表中调用了代理构造函数初始化某个类成员变量之后,就不能在初始化列表中再次初始化这个变量了
// 错误, 使用了委托构造函数就不能再次m_max初始化了 Test(int max, int min) : Test(max), m_max(max) { this->m_min = min > 0 && min < max ? min : 1; }

2 继承构造函数

C++11 中提供的继承构造函数可以让派生类直接使用基类的构造函数,而无需自己再写构造函数尤其是在基类有很多构造函数的情况下,可以极大地简化派生类构造函数的编写。先来看没有继承构造函数之前的处理方式

class Base { public: Base(int i) :m_i(i) {} Base(int i, double j) :m_i(i), m_j(j) {} Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) {} int m_i; double m_j; string m_k; }; class Child : public Base { public: Child(int i) :Base(i) {} Child(int i, double j) :Base(i, j) {} Child(int i, double j, string k) :Base(i, j, k) {} }; int main() { Child c(520, 13.14, "i love you"); cout << "int: " << c.m_i << ", double: " << c.m_j << ", string: " << c.m_k << endl; return 0; }

我们通过继承构造函数在子类中重新定义和基类一样的构造函数:通过使用using 基类名::基类的构造函数名来使用基类的构造函数,这样子类中就可以不定义相同的构造函数了,直接使用基类的构造函数来构造派生类对象

class Base { public: Base(int i) :m_i(i) {} Base(int i, double j) :m_i(i), m_j(j) {} Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) {} int m_i; double m_j; string m_k; }; class Child : public Base { public: using Base::Base; // 引入父类Base的构造函数及其重载 }; int main() { Child c(520, 13.14, "i love you"); cout << "int: " << c.m_i << ", double: " << c.m_j << ", string: " << c.m_k << endl; return 0; }

在修改后的子类中,没有添加任何构造函数,而是添加了using Base::Base这样就可以在子类中直接继承父类的所有的构造函数,通过他们去构造子类对象了。

此外,如果在子类中隐藏了父类中的同名函数,也可以通过 using 的方式在子类中使用基类中的这些父类函数

class Base { public: Base(int i) :m_i(i) {} Base(int i, double j) :m_i(i), m_j(j) {} Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) {} void func(int i) { cout << "base class: i = " << i << endl; } void func(int i, string str) { cout << "base class: i = " << i << ", str = " << str << endl; } int m_i; double m_j; string m_k; }; class Child : public Base { public: using Base::Base; // 引入父类Base的构造函数及其重载 using Base::func; // 引入父类Base的func函数及其重载 void func() { cout << "child class: i'am huang" << endl; } }; int main() { Child c(250); c.func(); c.func(18); c.func(18, "huang"); return 0; }

输出结果

child class: i'am huang base class: i = 18 base class: i = 18, str = huang

子类中的func()函数隐藏了基类中的两个func(),默认情况下通过子类对象只能调用无参的func(),在上面的子类代码中添加了using Base::func之后,就可以通过子类对象直接调用父类中被隐藏的带参 func() 函数了。

这里插入一个注意事项,在 C++ 中,当我们在派生类中没有重写基类的重载函数之一的时候,在派生类中调用重载函数时是可以在其基类中查到的。然而,当我们想在子类中重写基类中某一个重载函数时,基类所有同名的重载函数会被隐藏,需通过using 基类名::函数名引入,才能让子类对象正常调用基类的重载函数。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 3:46:44

树莓派零成本自动化侦察实战指南:theHarvester高性能部署方案

树莓派零成本自动化侦察实战指南&#xff1a;theHarvester高性能部署方案 【免费下载链接】theHarvester E-mails, subdomains and names Harvester - OSINT 项目地址: https://gitcode.com/GitHub_Trending/th/theHarvester 面对网络安全评估中开源情报收集工具匮乏的…

作者头像 李华
网站建设 2026/4/18 3:45:42

豆包手机被微信「拒绝」后,阿里系 APP 被曝也禁止其登陆,如何看待这场「博弈」?核心矛盾是什么?

最近&#xff0c;豆包手机成为了全网热议的焦点。这款备受期待的 AI 手机在发布后短短几天内便遭遇了微信、淘宝等主流应用的封禁&#xff0c;不仅如此&#xff0c;其他阿里系应用也接连宣布禁止该设备登录。这一波波的封杀让无数网友感到震惊&#xff0c;更引发了关于技术、商…

作者头像 李华
网站建设 2026/4/18 3:47:33

字节跳动计算机使用智能体技术架构深度解析

字节跳动计算机使用智能体技术架构深度解析 【免费下载链接】UI-TARS-2B-SFT 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/UI-TARS-2B-SFT 在人工智能从语言理解向自主操作演进的关键节点&#xff0c;字节跳动推出的计算机使用智能体&#xff08;Comp…

作者头像 李华
网站建设 2026/4/18 0:52:44

(新卷)产品模块算法检验(Java、Js、c\c++、python)

产品模块算法检验 在产品配置中&#xff0c;一个配置产品是由多个产品模块(CM)构成&#xff0c;每个CM有自身的算法&#xff0c;且模块间可能存在算法依赖。例如电脑产品是由主板、CPU日、显卡等CM构成。CPU模块(CM1)算法依赖主板模块(CM2)算法&#xff0c;记作CM2<-CM1,算法…

作者头像 李华
网站建设 2026/4/16 18:43:55

RTCP: 统计、同步与网络自适应

RTCP: 统计、同步与网络自适应 本文是 WebRTC 系列专栏的第十三篇,将深入剖析 RTCP 协议的工作原理,包括 Sender/Receiver Report、网络质量反馈以及音视频同步机制。 目录 RTCP 概述RTCP 包类型Sender Report (SR)Receiver Report (RR)丢包、带宽与延迟分析音视频同步 (Lip-S…

作者头像 李华
网站建设 2026/4/10 20:39:23

DuckDB嵌入式分析数据库终极指南:快速上手高性能数据处理

DuckDB嵌入式分析数据库终极指南&#xff1a;快速上手高性能数据处理 【免费下载链接】duckdb DuckDB is an in-process SQL OLAP Database Management System 项目地址: https://gitcode.com/GitHub_Trending/du/duckdb 在当今数据驱动的时代&#xff0c;嵌入式分析数据…

作者头像 李华