码迷,mamicode.com
首页 > 编程语言 > 详细

Effective C++ 条款45

时间:2015-06-07 15:52:39      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:explicit   模板隐式转化   

本节条款的题目是运用成员模板接受所有兼容类型

作者阐述自己的观点是通过智能指针的例子。
在学习本节条款之前我们要先明白关于隐式转化的问题
如下代码:

#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操作符。

Effective C++ 条款45

标签:explicit   模板隐式转化   

原文地址:http://blog.csdn.net/u011058765/article/details/46401111

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!