细读《Effective C++》之七

来源:互联网 发布:淘宝代销产品怎么发货 编辑:程序博客网 时间:2024/04/28 21:01
 

Chapter 6. Inheritance and Object-Oriented Design

Item 32 - 34

条款32:Make sure public inheritance models "is-a"

在写代码的时候,如果我用public的方式从base classes继承derived classes,那是因为别人也是这样做的,或者,是因为我在多个derived clases中要用到base classse的相同接口和成员变量,而且我希望derived classes能像base classes一样使用所有这一切。

Scott提醒我们,不是所有的bird都能fly,例如penguin;如果这是可以理解的,离奇的是:square is a rectangle不成立,我左思右想,难以理解,往下一看:矩形可以任意加高加宽……

Things to Remember

Public inheritance means "is-a." Everything that applies to base classes must also apply to derived classes, because every derived class object is a base class object.

条款33:Avoid hiding inherited names

当base classes的member functions被derived classes重载,这就意味着在derived classes中,被重载函数的base classes的member functions将从此永久性地淡出你的视野。鱼与熊掌兼得的方法还是有的:

class Derived: public Base {
public
:
  
using Base::mf1;       // make all things in Base named mf1 and mf3

  using Base::mf3;       // visible (and public) in Derived's scope

  
virtual void mf1();
  
void
 mf3();
  
void
 mf4();
  ...
};

按照Scott的说法,我们必须要保证public inheritance的is-a关系,也就必须使用using来保证base classes的所有函数被public inheritance。否则,就不要使用public inheritance。当然在private inheritance中也有办法使用base classes的函数:forwarding functions。

class Derived: private Base {
public
:
  
virtual void mf1()                   // forwarding function; implicitly

  { Base::mf1(); }                     // inline (see Item 30)
  ...
};

Things to Remember

1) Names in derived classes hide names in base classes. Under public inheritance, this is never desirable.

2) To make hidden names visible again, employ using declarations or forwarding functions.

条款34:Differentiate between inheritance of interface and inheritance of implementation

在读过GoF后,我对interface inheritance和implementation inheritance的理解是:在base classes中interface inheritance functions声明为pure virtual,而implementation inheritance functions声明为non-virtual,二者兼有的声明为impure virtual。

class Shape {
public
:
  
// have derived classes inherit a function interface only

  virtual void draw() const = 0;
  
  
// have derived classes inherit a function interface as well as a default implementation

  virtual void error(const std::string& msg); 
  
  
// have derived classes inherit a function implementation only

  int objectID() const;
  ...
};

在看过这一款之后,我整理了以下几点:

1) pure virtual functions也可以被调用:

Shape *ps = new Ellipse;           // fine
ps->Shape::draw();                 // calls Shape::draw

原来,pure virtaul functions必须在derived classes中重新声明并实现,但也可以在base classes中被实现。

2) impure virtual functions的最大问题在于即使derived classes很容易因为使用缺省impure virtual functions而导致隐患,两种处理方式:

a) 改作pure virtual functions,在base classes中只提供接口,并定义protected的non-virtual default implementations,以保证其不被重写,而在derived classes中予以实现时,直接调用base classes中的non-virtual default implementations。

b) 既然pure virtaul functions也可以在base classes中被实现,这样的pure virtaul functions就可以被看作两部分:declaration表现的是interfaces,definition表现的是implementations。

3) 没有实现的pure virtual functions只提供接口;有实现的pure virtual functions提供接口和缺省实现;non-virtual functions提供接口和强制实现。看来没有impure virtual functions什么事儿了。

Things to Remember

1) Inheritance of interface is different from inheritance of implementation. Under public inheritance, derived classes always inherit base class interfaces.

2) Pure virtual functions specify inheritance of interface only.

Simple (impure) virtual functions specify inheritance of interface plus inheritance of a default implementation.

3) Non-virtual functions specify inheritance of interface plus inheritance of a mandatory implementation.