zoukankan      html  css  js  c++  java
  • Effective C++ 条款45 运用成员函数模板接受所有兼容类型

    1. "智能指针"是行为像指针的对象,但它们能提供指针没有的功能:shared_ptr,weak_ptr,auto_ptr(见条款13)实现对堆内存的自动管理,STL的迭代器实现对整个容器的遍历等.

        C++内置类型指针(int*,char*等)的优势在于支持继承层次中派生类指针向基类指针的转换(当然标准库shared_ptr,weak_ptr,auto_ptr等已实现).

    2. 由于同一template的不同实例化之间没有直接联系,也就是说对于自定义的智能指针(假设名为SmartPtr),如果不额外采取手段支持基层层次中派生类指针向基类指针的转换,那么SmartPtr<Base>和SmartPtr<Derived>将会被编译器认为毫无关联,也就不存在SmartPtr<Derived>向SmartPtr<Base>的隐式转换.

        要获得Smart classes之间的隐式转换能力,就要明确地写出用于隐式转换的构造函数.

        假设存在一个Base类,要实现由SmartPtr<Base的派生类>向SmartPtr<Base>的转换,显然无法为SmartPtr写出所有用于隐式类型转换的copy构造函数,因为Base的继承体系的扩充可能性是无限的.因此只能采用成员函数模板做到一劳永逸:

    template<typename T>
    class SmartPtr{
    public:
        template<typename U>
        SmartPtr(const SmartPtr<U>& other);  //生成copy构造函数用于隐式转换
        ....
    }
    View Code

        以上代码SmartPtr的copy构造函数的含义是对于任何类型U和类型T,都可以根据类型Smart<U>生成一个Smart<T>,因为SmartPtr<U>和SmartPtr<T>是同一template的不同实例化,因此这种构造函数被称为泛化copy构造函数.SmartPtr的泛化copy构造函数并没有被声明为explict,是为了模仿原始指针之间的隐式转换.

        以上copy构造函数的声明并无法将SmartPtr之间的转换局限在可转换的原始指针之间,因此要在SmartPtr实现中SmartPtr之间的转换进行限制,假设SmartPtr像auto_ptr一样提供了用于获取原始指针的get函数,那么SmartPtr(const SmartPtr<U>& other)的实现可能像这样:

    template<typename T>
    class SmartPtr{
    public:
        template<typename U>
        SmartPtr(const SmartPtr<U>& other):helder(other.get()){}
        T* get() const {
            return haldPtr;
        }
        ...
    private:
        T* heldPtr;
    }
    View Code

        这样就把检查底层指针能否转换的任务交由底层指针来自行检查.

    3. 成员模板函数(member template function)的效用并不局限于构造函数,它们的另一个常见作用是支持赋值操作.tr1的shared_ptr支持所有兼容的内置指针,tr1::shared_ptrs,auto_ptrs和weak_ptrs"的构造行为,以及所有来自上述物(除weak_ptr)的的赋值操作,以下是摘自TR1规范中关于tr1::shared_ptr的一份摘录:

    template<typename T>
    class shared_ptr{
    public:
        template<class Y>    //声明类型参数时class和typename含义相同
            explict shared_ptr(Y* p);
        template<class Y>
            shared_ptr(shared_ptr<Y> const& r);
        template<class Y>
            explict shared_ptr(weak_ptr<Y> const& r);
        template<class Y>
            explict 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);
        ...
    }
    View Code

        以上所有构造函数都为explict,唯有泛化copy构造函数除外,这意味着shared_ptr允许shared_ptr之间的隐式类型转换,而禁止原始指针或其他智能指针类型向shared_ptr的转换;此外,传递给tr1::shared_ptr构造函数和赋值操作符的auto_ptr并未被声明const,因为auto_ptr在这之后会被置为NULL.

    4. 需要注意的是,虽然成员函数模板(member function template)可以实例化出用于shared_ptr<T>向shared_ptr<T>转换的copy构造函数,但如果没有声明copy构造函数,编译器还是会合成一个,所以不能依赖于成员函数模板的实例化,要手动声明一个普通的copy构造函数.copy赋值操作符也是一样.

  • 相关阅读:
    微信 token ticket jsapi_ticket access_token 获取 getAccessToken get_jsapi_ticket方法
    PHP 日志 记录 函数 支持 数组 对象 新浪 sae 环境 去掉 空格 换行 格式化 输出 数组转字符串
    原生 原始 PHP连接MySQL 代码 参考mysqli pdo
    PHP 数字金额转换成中文大写金额的函数 数字转中文
    使用PHPMailer发送带附件并支持HTML内容的邮件
    设置输出编码格式 header 重定向 执行时间 set_time_limit 错误 报告 级别 error_reporting
    html5 bootstrap pannel table 协议 公告 声明 文书 模板
    指向指针的指针
    二级指针
    c语言:当指针成为参数后
  • 原文地址:https://www.cnblogs.com/reasno/p/4802034.html
Copyright © 2011-2022 走看看