美文网首页Exceptional C++
【Exceptional C++(13)】使用/滥用继承

【Exceptional C++(13)】使用/滥用继承

作者: downdemo | 来源:发表于2018-01-29 15:52 被阅读11次

    问题

    • 耦合关系要尽量减少,如果class和class之间有多种方式表达,使用关系最弱的一种,继承是C++所能表达的最强烈关系,只有在没有性能相近的更弱关系时才使用继承
    • 以下template提供了list的管理功能,包括特定list位置上处理元素的能力
    // Example 1
    template <class T>
    class MyList {
    public:
        bool Insert(const T&, size_t index);
        T Acess(size_t index) const;
        size_t Size() const;
    private:
        T* buf;
        size_t bufsize;
    };
    
    • 考虑下面代码,以MyList为基础实现一个MySet
    template <class T>
    class MySet1 : private MyList<T>
    {
    public:
        bool Add(const T&); // call Insert()
        T Get(size_t index) const;
        // call Acess()
        using MyList<T>::Size;
        ...
    };
    template <class T>
    class MySet2
    {
    public:
        bool Add(const T&); // call impl_.Insert()
        T Get(size_t index) const;
        // call impl_.Acess()
        size_t Size() const; // call impl_.Size()
        ...
    private:
        MyList<T> impl_;
    };
    
    • MySet1和MySet2有区别吗?nonpublic inheritance和containment有什么不同?

    解答

    • 两者没有实际意义上的区别,因为它们功能相同
    • nonpublic inheritance应该总是表现出is implemented in terms of的意义,containment总是表现出has a的意义,连带也有is implemented in terms of的意义。可见inheritance是single containment的一个超集,可以用MyList<T> member完成的都可以用继承自MyList<T>完成。inheritance只能拥有一份MyList<T>作为base subobject,如果需要拥有多份MyList<T>实体,就要用containment
    • 尽量用aggregation(也叫composition、layering、has-a、delegation)取代inheritance
    • 需要使用inheritance的理由
      • 需要重写虚函数,这是inheritance的经典使用理由
      • 需要处理protected member
      • 需要在一个base subobject之前构建used object,或在之后摧毁used object
      • 需要分享某个共同的虚基类或重写虚基类的构建程序
      • 从只有函数没有成员变量的empty base class继承不会增加空间负担,能获得最佳收益
      • 需要实现受限制的多态,即LSP ISA,一个受到束缚的IS-A关系
    • 分析MySet看看是否适用上述标准
      • MyList没有protected member,所以不需要继承来存取
      • MyList没有虚函数,不需要继承重写
      • MyList没有其他基类,所以MyList对象不需要在另一个basesubobject之前构建或之后销毁
      • MyList没有虚基类是需要共享的或construction需要重写
      • MyList不是空的,不适用empty base class最佳化
      • MySet不是一个IS-NOT-A MyList
    • 所以MySet不应继承MyList,下面重写MySet2,以更广泛的方式使用containment,不只是以MyList<T>为基础具现,标准库就是用这项技术来完成stack和deque两个template的
    template <class T, class Impl = MyList<T>>
    class MySet3
    {
    public:
        bool Add(const T&); // call impl_.Insert()
        T Get(size_t index) const;
        // call impl_.Acess()
        size_t Size() const; // call impl_.Size()
        ...
    private:
        Impl impl_;
    };
    

    相关文章

      网友评论

        本文标题:【Exceptional C++(13)】使用/滥用继承

        本文链接:https://www.haomeiwen.com/subject/lbixzxtx.html