menu

hjk41的日志

Avatar

Effective C++ 36: Differentiate between inheritance of interface and inheritance of implementation

There are three types of member functions, namely pure virtual functions, simple (nonpure) functions, and nonvirtual functions.
Here is an example:

class Shape {
public:
  virtual void draw() const = 0;
  virtual void error(const string& msg);
  int objectID() const;
  ...
};
class Rectangle: public Shape { ... };
class Ellipse: public Shape { ... };


A pure virtual member function means that:
1. The class must be used as a base class, and no instance of the class should be created.
2. The derived classes inherit the function interface only.
A nonpure virtual member functions means that the derived classes inherit the functions interface as well as a default implementation.
A nonvirtual member function means that the function interface and implementation is identical among all the derived classes, and should not be changed.

A nonpure vitual member function provides derived classes with a default implementation, but it allows them to inherit the implementation without explicitly saying that. This is problematic sometimes. If we want to provide a default implementation and at the same time want the derived classes to explicitly ask for it, there is two ways.
1. Declare a pure virtual function and give it a definition.

class Shape {
public:
  virtual void draw() const = 0;
  virtual void error(const string& msg);
  int objectID() const;
  ...

  virtual void fill() =0;
};
class Rectangle: public Shape { ... };

class Line: public Shape{ ... };   // a line can not be filled

void Shape::fill(){
 [i] // a default implementation of fill[/i]
  ...
}

void Rectangle::fill(){
  Shape::fill();  // explicitly call the funciton
}

Rectangle * r=new Rectangle;
Line * l=new Line;
r->fill();   // ok, no problem
l->fill();    // error, fill() not defined in l

2. Declare a pure virtual member function and provide a nonvirtual default one.

class Shape {
public:
  virtual void draw() const = 0;
  virtual void error(const string& msg);
  int objectID() const;
  ...

  virtual void fill() =0;
protected:
  void DefaultFill();
};
class Rectangle: public Shape { ... };

class Line: public Shape{ ... };   // a line can not be filled

void Shape::DefaultFill(){
 [i] // a default implementation of fill[/i]
  ...
}

void Rectangle::fill(){
  DefaultFill();   // explicitly call the funciton
}

Rectangle * r=new Rectangle;
Line * l=new Line;
r->fill();   // ok, no problem
l->fill();    // error, fill() not defined in l


评论已关闭