【Effection C++】读书笔记 条款38~条款39

【Effection C++】继承与面向对象设计

条款38:通过复合塑模出has-a或“根据某物实现出”

复合(composition)是类型之间的一种关系,当某种类型的对象内涵它种类型的对象,便是这种关系。复合意味着出has-a(有一个)或is-implemented-in-terms-of(根据某物实现出)。

has-a 复合关系

class Person
{
private:
    // has a string类型的变量
    string Name; 
    // has a PhoneNumber对象
    PhoneNumber HomeNumber; 
    // has a TelephoneNumber对象
    PhoneNumber TelephoneNumber;
};

对于这个例子,我们就可以说Person has a Name,Person has a HomeNumber,Person has a TelephoneNumber,

is-implemented-is-of 复合关系

在这里拿出来书上的例子,以STL中的list来实现新版本的一个set,注重空间而不注重效率。

  1. 无法让你新建的set继承STL中的list来实现功能,因为这无法满足public继承是一种is-a的关系。显然set不是一个list。
  2. 这里考虑本条款中的复合关系,显然我们可以通过list来实现set。

示例代码如下:

template<typename T>  
class Set  
{  
public:  
    bool member(const T& item)const  
    {  
        return find(rep.begin(),rep.end(),item) != rep.end();  
    }  
    void insert(const T& item)  
    {  
        if(!member(item))  
            rep.push_back(item);  
    }  
    void remove(const T& item)  
    {  
        typename list::iterator it = find(rep.begin(),rep.end(),item);  
        if(it != rep.end())  
            rep.erase(it);  
    }  
    size_t size()const  
    {  
        return rep.size();  
    }  
    void print()  
    {  
        list::iterator it = rep.begin();  
        for(;it != rep.end();++it)  
            cout<<*it<<"\t"<private:  
    list rep;  //通过list来实现set
};  

条款39:明智而审慎的使用private继承

private继承的规则为:
1. 如果classes之间的继承关系是private,编译器不会自动将一个derived class对象转换为一个private.
2. 由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原本是protected或public属性。

private继承意味着implemented-in-terms-of,根据某物实现出。

private继承意味着implemented-in-terms-of,根据某物实现出,而条款38也指出复合的意义也是如此。那么应该如何在两者之间进行取舍呢?

答:尽可能的使用复合,只有在必要时候才是有private继承,即主要是当protected成员,和/或 需要重新定义其中的virtual成员函数,还有一种情况就是,如果相应的base class不带有任何数据时候,无non-static成员变量,无virtual函数,也无virtual base classes。而代码又比较在意内存空间的大小,就可以使用继承方式来完成操作。

这主要是由于空白基类最优化(empty base optimization-EBO 或 empty base classopimization-EBCO)的作用。在空基类被继承后由于没有任何数据成员,所以子类优化掉基类所占的1 byte。EBO并不是c++标准所规定必须的,但是大部分编译器都会这么做。

要注意EBO一般只在单一继承下而非多重继承下才可行。

最后:

  1. private继承意味着is-implemented-in-terms of(根据某物实现出)。它通常比复合(composition)的级别低。但是当derived class需要访问 protected base class的成员,或者需要重新定义继承而来的virtual函数时,这个设计是合理的。
  2. 和复合(composition)不同,private继承可以造成空白基类最优化,它虽然不是C++标准所规定的,但是几乎在所有编译器上都实现了。这对致力于对象尺寸最小化的程序库开发者而言,可能很重要。

你可能感兴趣的:(读书笔记,effective-c++,c++)