Effective C++ 条款45
本节条款的题目是运用成员模板接受全部兼容类型
作者阐述自己的观点是通过智能指针的样例。
在学习本节条款之前我们要先明确关于隐式转化的问题
例如以下代码:
#include<iostream>
using namespace std;
class A
{
public:
explicit A(int i):a(i){};
A(const A&obj):a(obj.a)
{
}
private:
int a;
};
int main()
{
int value =0;
A a = value;//编译不通过。由于构造函数中有explicit限定符
return 0;
}
我们知道由于explicit限定符的存在编译不通过。
以下我们看另一段书上的代码:
template<typename T>
class SmartPrt{
public:
explicit SmartPtr(T* realPtr);
……
};
SmartPtr<Top> pt1=SmartPtr<Middle>(new Middle);
SmartPrt<Top> pt2=SmartPrt<Bottom>(new Bottom);
SmartPrt<const Top> pct2=pt1;
我们能够知道,由于`SmartPtr<Top>`类型和`SmartPtr<Middle>`
类型不同。再加上explicit SmartPtr<Middle>
中的explicit限定符,SmartPtr<Top> pt1=SmartPtr<Middle>(new Middle);
这句代码编译不通过。
并且编译器并不觉得SmartPtr<Top>
类型和SmartPtr<Middle>
类型存在继承关系。
为了能够实现相互转化。能够加入本节的主旨技术去解决上面出现的问题。
例如以下代码:
template<typaname T>
class SmartPtr{
public:
template<typename U>
SmartPrt(const SmartPrt<U>& other)
:heldPrt(other.get()){};
T* get() const{return heldPrt;}
……
private:
T* heldPrt;
};
SmartPtr<Top> pt1=SmartPtr<Middle>(new Middle);
SmartPrt<Top> pt2=SmartPrt<Bottom>(new Bottom);
SmartPrt<const Top> pct2=pt1;
我们加入了一个member function template函数。由于typename T和typename U 是两种类型,并且构造函数中没有explicit关键字,不会阻止heldPrt(other.get())的隐式转换
。
所以,以上代码能够通过编译。
作者最后列出了TR1规范中关于tr1::shared_ptr的一份摘录
例如以下:
template<class T>
class shared_ptr{
public:
template<class Y>
explicit shared_ptr(Y* p);
template<class Y>
shared_ptr(shared_ptr<Y> const& r);
template<class Y>
explicit shared_ptr(weak_ptr<Y> const& r);
template<class Y>
explicit shared_ptr(auto_ptr<Y> const& r);
template<class Y>
shared_ptr& operator=(shared_ptr<Y> const& r);
template<class Y>
shared_ptr& operator=(auto_ptr<Y> const& r);
……
};
我们能够发现上面仅仅有泛化copy构造函数不是explicit,表示shared_ptr 的隐式转化被同意,而其它的智能指针转化不被同意。
这里另一个须要注意的地方,在class类声明泛化copy构造函数(member template)。并不会阻止编译器生成它们自己的copy构造函数(non-template),换言之。假设程序中仅仅写了泛化的copy构造函数,那么编译器还是会自己主动生成一个非泛化的版本号出来,假设不想要这个缺省版本号,那一定不能偷懒。要两个版本号的copy构造函数都要写。
代码例如以下:
template<typaname T>
class SmartPtr{
public:
template<typename U>
SmartPrt(const SmartPrt<U>& other)
:heldPrt(other.get()){};
SmartPtr(){}//假设不写自己的非泛化构造函数,编译器会自己主动生成自己的默认非泛化构造函数。
T* get() const{return heldPrt;}
……
private:
T* heldPrt;
};
最后:
作者总结例如以下:
1. 请使用member function templates(成员函数模板)生成“可接受全部兼容类型”的函数。
2. 假设你声明member templates用于“泛化copy构造”或“泛化assignment操作”,你还是须要声明正常的copy构造函数和copy assignment操作符。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架