美文网首页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