条款45:运用成员函数模板结合艘所有的兼容类型

首先看看下面的真实的指针与模板创建的智能指针之间的区别:

1 class Top{...};
2 class Middle : public Top{...};
3 class Bottom : public Middle{...};
4 Top * p1 = new Bottom();
5 Top * p2 = new Middle();
6 const Top * cp2 = p1;     //ok,没有问题,指针与实际所指之物之间确实是有关系的

但是:

1 template<typename T>
2 class SmartPtr{
3 public:
4     explicit SmartPtr(T * ptr);
5     ...
6 };
7 SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle);
8 SmartPtr<Top> pt2 = SmartPtr<Bottom>(new Bottom);
9 SmartPtr<const Top> cp2 = pt1;

这里的等式左右两边的真正实际并没有任何的关系,只是同一个模板实例化出来的不同模板实例而已。

1 template<typename T>
2 class SmartPtr{
3 public:
4     template<typename U>
5     SmartPtr(const SmartPtr<U> &other);
6     ...
7 };

上面这个SmartPtr的构造函数并非是explicit的,因为默认的指针之间可以隐式的相互转换,所以将这点引申到智能指针之上也是无可厚非的。

 1 template<typename T>
 2 class SmartPtr{
 3 public:
 4     template<typename U>
 5     SmartPtr(const SmartPtr<U> &other)
 6     : heldPtr(other.get()){...}
 7     T*get() const{return heldPtr;}
 8     ...
 9 private:
10     T * heldPtr;
11 };

在这种情况下,上面的那个构造函数的定义的意思:存在某个隐式的转换关系,可以将U类型的指针转换成T类型的指针才可以,这正好符合我们想将一个继承体系里面的指针相互转换的这种行为。

小结:

请使用member function templates 生成,可接受所有兼容类型的函数

对member function template 如果要定义拷贝构造函数以及拷贝赋值运算符(template版本)的话,那么也应该定义一般的构造函数与拷贝赋值运算符(非template版本)。

时间: 2024-10-13 04:40:07

条款45:运用成员函数模板结合艘所有的兼容类型的相关文章

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

1. "智能指针"是行为像指针的对象,但它们能提供指针没有的功能:shared_ptr,weak_ptr,auto_ptr(见条款13)实现对堆内存的自动管理,STL的迭代器实现对整个容器的遍历等. 真正的指针的优势在于支持继承层次中派生类指针向基类指针的转换(当然标准库shared_ptr,weak_ptr,auto_ptr等已实现). 2. 由于同一template的不同具现体之间没有直接联系,也就是说对于自定义的智能指针(假设名为SmartPtr),如果不额外采取手段支持基层层次

Effective C++ Item 45 运用成员函数模板接收所有兼容类型

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:请使用 member function templates(成员函数模板)生成"可接受所有兼容类型"的函数 示例:泛化 copy 构造函数 temmplate<typename T> class SmartPtr{ public: template<typename U> SmartPtr(const SmartPtr<U> &o

读书笔记 effective c++ Item 45 使用成员函数模板来接受“所有兼容类型”

智能指针的行为像是指针,但是没有提供加的功能.例如,Item 13中解释了如何使用标准auto_ptr和tr1::shared_ptr指针在正确的时间自动删除堆上的资源.STL容器中的迭代器基本上都是智能指针:当然,你不能通过使用“++”来将链表中的指向一个节点的内建指针移到下一个节点上去,但是list::iterator可以这么做. 1. 问题分析——如何实现智能指针的隐式转换 真正的指针能够做好的一件事情是支持隐式转换.派生类指针可以隐式转换为基类指针,指向非const的指针可以隐式转换成为

C++程序设计方法4:成员函数模板

成员函数的模板: 普通类的成员函数,也可以定义为函数模板,如: class normal_class { public: int value; template<typename T> void set(T const &v) { value = int(v);//在类内定义 } template<typename T> T get(); }; template<typename T> T normal_class::get() {return T(value)

C++学习45 流成员函数put输出单个字符 cin输入流详解 get()函数读入一个字符

在程序中一般用cout和插入运算符“<<”实现输出,cout流在内存中有相应的缓冲区.有时用户还有特殊的输出要求,例如只输出一个字符.ostream类除了提供上面介绍过的用于格式控制的成员函数外,还提供了专用于输出单个字符的成员函数put.如:    cout.put('a');调用该函数的结果是在屏幕上显示一个字符a.put函数的参数可以是字符或字符的ASCII代码(也可以是一个整型表达式).如    cout.put(65 + 32);也显示字符a,因为97是字符a的ASCII代码. 可以

C++ - 模板类模板成员函数(member function template)隐式处理(implicit)变化

模板类模板成员函数(member function template)隐式处理(implicit)变化 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24233693 指针支持隐式转换(implicit conversion), 在动态绑定中,派生类指针能够转换为基类指针. 可是模板的实例化(instantiations)之间, 是单独存在的, 派生类的实例化的模板(SmartPtr<Derived>), 不能转换为基类实例

C++模板编程中只特化模板类的一个成员函数

模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全部重写该模板类的所有成员函数,不但会增加工作量,也不利于代码的维护. 例如下面的类模板A,只有在模板参数是char*时才需要特化成员函数func(),但其他的成员函数都不需要特化: 1 template <typename _Ty> 2 struct A 3 { 4 // 其他成员函数a 5 //

C++模板编程中只特化模板类的一个成员函数(花样特化一个成员函数)

转自:https://www.cnblogs.com/zhoug2020/p/6581477.html 模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全部重写该模板类的所有成员函数,不但会增加工作量,也不利于代码的维护. 例如下面的类模板A,只有在模板参数是char*时才需要特化成员函数func(),但其他的成员函数都不需要特化: 1 templ

类模板、模板类、函数模板、模板函数

一:什么是类模板 一个类模板允许用户为类定义一种模式,使得类中的某些数据成员.默认成员函数的参数.某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的) 如果一个类中数据成员的数据类型不能确定.或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的.实际的类,而是代表一类类. 二:类模板定义及注意事项 template<class 模板参数表> 或者template<typename 模板参数表> class 类名 { /