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赋值操作符也是一样.

  • 相关阅读:
    浅析电商防止恶意下单
    Dubbo与Hadoop RPC的区别
    中秋福利 | 10本技术图书(编程语言、数据分析等)免费送
    IOS渠道追踪方式
    数据迁移的应用场景与解决方案Hamal
    JVM锁实现探究2:synchronized深探
    网页设计简史看设计&代码“隔膜”
    知物由学 | 你真的了解网络安全吗?
    一行代码搞定Dubbo接口调用
    测试周期内测试进度报告规范
  • 原文地址:https://www.cnblogs.com/reasno/p/4802034.html
Copyright © 2011-2022 走看看