新闻详情

新闻详情

首页 / 资讯中心 / 详情

Effective C++ 学习笔记 条款45 运用成员函数模板接受所有兼容类型

发布时间:2026/8/31 15:00:07来源:尧图网络
Effective C++ 学习笔记 条款45 运用成员函数模板接受所有兼容类型
智能指针是行为很像指针但提供了指针所不具备之功能的对象。例如条款13解释了标准库中的 auto_ptr 和 tr1::shared_ptr 如何能在适当的时机自动删除堆上分配的资源。STL 容器的迭代器几乎都是智能指针你当然不能指望通过“”将一个内置指针从链表的一个节点移到下一个节点但对于 list::iterator 来说这却是可行的。真实指针做得很好的事情之一是支持隐式转换。派生类指针隐式转换为基类指针指向非 const 对象的指针转换为指向 const 对象的指针等等。例如考虑在一个三层继承体系中可能发生的一些转换在用户自定义的智能指针类中模拟这样的转换是棘手的。我们需要让以下代码能够编译同一模板的不同实例化之间没有内在关系所以编译器把SmartPtrMiddle和SmartPtrTop视为完全不同的类它们之间的关联并不比vectorfloat和Widget更密切。为了获得我们想要的 SmartPtr 类之间的转换我们必须显式地对它们进行编程。在之前的智能指针示例代码中每条语句都创建了一个新的智能指针对象所以现在我们重点讨论如何编写行为符合我们预期的智能指针构造函数。一个关键的观察是我们无法写出所有我们需要的构造函数。在上面的继承体系中我们可以从SmartPtrMiddle或SmartPtrBottom构造SmartPtrTop但如果未来扩展了继承体系SmartPtrTop对象还必须能够从其他智能指针类型构造。例如如果我们后来添加了我们就需要支持从SmartPtrBelowBottom对象创建SmartPtrTop对象而我们当然不想为了这个而修改 SmartPtr 模板。从原则上讲我们需要的构造函数数量是无限的。既然模板可以被实例化以生成无限数量的函数看来我们需要的不是 SmartPtr 的一个构造函数而是一个构造函数模板。这类模板就是成员函数模板通常简称为成员模板的例子——即生成类的成员函数的模板这表示对于每一个类型 T 和每一个类型 U都可以从一个SmartPtrU创建一个SmartPtrT因为SmartPtrT有一个接受SmartPtrU参数的构造函数。像这样的构造函数——从一个类型为同一模板的不同实例化的对象创建另一个对象的构造函数例如从SmartPtrU创建SmartPtrT——有时被称为泛化拷贝构造函数generalized copy constructors。上面的泛化拷贝构造函数没有声明为 explicit。这是有意为之的。内置指针类型之间的类型转换例如从派生类指针到基类指针是隐式的不需要强制转型所以智能指针模拟这种行为是合理的。省略模板化构造函数上的 explicit 正好做到了这一点。按照上述声明SmartPtr 的泛化拷贝构造函数提供的功能超出了我们想要的。是的我们希望能够从SmartPtrBottom创建SmartPtrTop但我们不希望能够从SmartPtrTop创建SmartPtrBottom因为那违背了 public 继承的含义参见条款32。我们也不希望能够从SmartPtrdouble创建SmartPtrint因为不存在从 double* 到 int* 的相应隐式转换。在某种程度上我们必须对这个成员模板将要生成的成员函数进行筛选。假设 SmartPtr 仿照 auto_ptr 和 tr1::shared_ptr 的做法提供了一个 get 成员函数该函数返回智能指针对象所持有的内置指针的一份副本参见条款15那么我们可以利用构造函数模板的实现来将转换限制为我们想要的类型我们使用成员初始化列表来将SmartPtrT中类型为 T* 的数据成员用SmartPtrU所持有的类型为 U* 的指针来初始化。只有当存在从 U* 指针到 T* 指针的隐式转换时这段代码才能编译而这正是我们想要的。最终效果是SmartPtrT现在拥有一个泛化拷贝构造函数只有当传入一个兼容类型的参数时才会编译通过。成员函数模板的用途并不仅限于构造函数。另一个常见的角色是支持赋值操作。例如TR1 的 shared_ptr同样参见条款13支持从所有兼容的内置指针、tr1::shared_ptr、auto_ptr 和 tr1::weak_ptr参见条款54进行构造并且还支持从除 tr1::weak_ptr 以外的所有这些类型进行赋值。下面是 TR1 规范中关于 tr1::shared_ptr 的一段摘录其中还包括它在声明模板参数时偏好使用 class 而非 typename 的习惯如条款42所解释的在此上下文中它们含义完全相同这些构造函数除了泛化拷贝构造函数之外都被声明为 explicit。这意味着允许从一种类型的 shared_ptr 到另一种类型的 shared_ptr 的隐式转换但不允许从内置指针或其他智能指针类型的隐式转换显式转换——比如通过强制转型——是允许的。同样有趣的是传递给 tr1::shared_ptr 构造函数和赋值操作符的 auto_ptr 参数没有被声明为 const这与 tr1::shared_ptr 和 tr1::weak_ptr 的传递方式形成对比。这是因为 auto_ptr 在被拷贝时会被修改这一点上它是独一无二的参见条款13。成员函数模板是很棒的东西但它们并不改变语言的基本规则。条款5解释说编译器可能生成的四个成员函数中有两个是拷贝构造函数和拷贝赋值操作符。tr1::shared_ptr 声明了一个泛化拷贝构造函数而且很明显当类型 T 和 Y 相同时泛化拷贝构造函数可以被实例化以创建“常规”拷贝构造函数。那么当从一个 tr1::shared_ptr 对象构造另一个同类型的 tr1::shared_ptr 对象时编译器是生成一个拷贝构造函数还是实例化泛化拷贝构造函数模板呢如我所说成员模板并不改变语言的规则而规则规定如果需要拷贝构造函数而你没有声明一个编译器会自动为你生成一个。在类中声明一个泛化拷贝构造函数一个成员模板并不能阻止编译器生成它们自己的拷贝构造函数一个非模板。因此如果你想控制拷贝构造的所有方面就必须同时声明泛化拷贝构造函数和“常规”拷贝构造函数。赋值操作也是如此。下面是一段摘自 tr1::shared_ptr 定义的示例说明了这一点切记1.使用成员函数模板来生成接受所有兼容类型的函数。2.如果你声明了用于泛化拷贝构造或泛化赋值的成员模板你仍然需要同时声明常规的拷贝构造函数和拷贝赋值操作符。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

基于微信小程序的师生互动桥系统毕业设计项目源码 2026/8/31 15:50:15

基于微信小程序的师生互动桥系统毕业设计项目源码

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

阅读更多 →
HTTP——服务端、客户端格式,浏览器解析 2026/8/31 15:50:15

HTTP——服务端、客户端格式,浏览器解析

bit::Shadow✧(≖ ◡ ≖✿ 目录 浏览器作为客户端,我的代码作为服务端。 抓取浏览器的HTTP格式的请求 请求行格式 请求行 请求头 空行 正文 请求方(Request) POST举例Login.html 见资源绑定(测试) 服务端应…

阅读更多 →
DeepSeek Harness 识图配置:ModLens + GLM-5.3 Flash 为 Agent 装上眼睛 2026/8/31 15:50:15

DeepSeek Harness 识图配置:ModLens + GLM-5.3 Flash 为 Agent 装上眼睛

这次我们来看 DeepSeek Harness 的识图配置。很多人在把 DeepSeek 接入到自己工具链之后,遇到的第一个需求往往是:Agent 只能读文字,不能看图。报错截图、页面截图、流程图、表格截图,全部没法处理。DeepSeek Harness 的 ModLens …

阅读更多 →
选题选错直接延毕[特殊字符]终于挖到不烂大街的论文选题神器 2026/8/31 15:50:15

选题选错直接延毕[特殊字符]终于挖到不烂大街的论文选题神器

无广实测|拒绝烂大街选题|选题不踩雷|轻松过导师初审✅ 过来人真心劝一句:论文写得再好,不如选对题! 很多人毕业翻车、开题被反复打回、写到一半写不下去,根本不是写作能力不行,是…

阅读更多 →
连续体机器人MATLAB源码:从建模到仿真全解析 2026/8/31 15:50:15

连续体机器人MATLAB源码:从建模到仿真全解析

简介:本资源是一套面向连续体机器人建模仿真与算法验证的MATLAB完整实现方案,专为计算机、人工智能、电子信息、自动化及机械电子等专业的高年级本科生与研究生设计,适用于课程设计、期末大作业及毕业设计中对柔性机器人运动学与动力学建模的…

阅读更多 →
深入理解 AI Agent · 多 Agent 编排 #03:Supervisor 与 Orchestrator——Dream-SaaS 双层编排架构拆解 2026/8/31 15:45:14

深入理解 AI Agent · 多 Agent 编排 #03:Supervisor 与 Orchestrator——Dream-SaaS 双层编排架构拆解

编排系列收官篇。前两篇分别讲了多 Agent 编排的四种核心模式(串行/并行/条件/竞争)和 Agent 间的通信、状态共享与冲突解决。本篇从概念落地到真实代码,以 Dream-SaaS 项目为例,拆解 Supervisor Orchestrator 双层编排架构的设计…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞