Differences between revisions 6 and 7
Revision 6 as of 2007-09-25 15:15:29
Size: 3295
Editor: T4d80
Comment: Example for inheriting an interface, inheriting an implementation, and inheritin
Revision 7 as of 2007-09-25 15:26:59
Size: 3590
Editor: T4d80
Comment: Make destructors virtual in base classes
Deletions are marked like this. Additions are marked like this.
Line 31: Line 31:
 1. The purpose of declaring a non-virtual function is to have derived classes inherit a function ''interface as well as a mandatory implementation''. (You want all derived classes to have exacly the same behavior.)  1. The purpose of declaring a non-virtual function is to have derived classes inherit a function ''interface as well as a mandatory implementation''. (You want all derived classes to have exactly the same behavior.)
Line 44: Line 44:




= Construction, destruction, and assignment =

== Make destructors virtual in base classes ==

Good rule of thumb: Make the destructor virtual if and only if the class contains at least one virtual function.

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7

This page covers design conventions that you should adhere to. Some of them have proven useful for OO design in general, others are special to C++ applications.

Many tips are taken from the book [http://www.aw-bc.com/catalog/academic/product/0,1144,0321334876,00.html Effective C++] by Scott Meyers.

Inheritance and object oriented design

Make sure (public) inheritance models "is a"

Whenever you derive a class D from a class B, every object of type D is a B in the sense that the derived class objects must be substitutable for the base class objects.

Do not do it as I (Joachim) have seen it in a real-world project: A person has properties, so CPerson inherits form CPersonProperties, which is a specialization of CProperties. This means, each CPerson is a CProperty, that is, each person is a property, which is non-sense at best, a catastrophic design flaw at worst.

Substitutability means means that objects of the derived class must behave in a manner consistent with the promises made in the base class' contract. Class D (and its methods) must require no more and promise no less than class B (and its overridden methods):

http://www.parashift.com/c++-faq-lite/proper-inheritance.html

In general, forget about "generalization" and "specialization". Think in terms of substitutability: In OO, a circle (which has one member for its radius) is not a specialization of an ellipse (which has two), though in mathematics it is one. The question is whether a circle can be put in wherever an ellipse can. (Most probably not, because it requires more: Even if a circle is considered to be an ellipse, it additionally requires that its two radii are the same.)

In the same sense, an ostrich (which cannot fly) is not a bird (if each bird has a method fly() that augments the bird's height over the ground):

http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.6

Differentiate between inheriting an interface, inheriting an implementation, and inheriting both of them

When should you make a method purely virtual, when non-purely (impurely?) virtual, and when non-virtual?

  1. The purpose of declaring a pure virtual function is to have derived classes inherit a function interface only. (You know too less for an implementation.)

  2. The purpose of declaring a simple (non-pure) virtual function is to have derived classes inherit a function interface as well as a default implemenation. (You can and want to give a default implementation, but let derived classes decide whether to override it.)

  3. The purpose of declaring a non-virtual function is to have derived classes inherit a function interface as well as a mandatory implementation. (You want all derived classes to have exactly the same behavior.)

class Car
{
public:
  virtual void driveToLocation(const Location& loc) = 0; // 1. Depends too much on the concrete car model (this makes the class abstract)
  virtual void hoot() { std::cout<< "Hoooooooot!" << std::endl;}    // 2. Some models may make a noise of their own
  const string getNumberPlate() { return _numberPlate; } // 3. Must be exactly this for all models
private:
  string _numberPlate;
}

Construction, destruction, and assignment

Make destructors virtual in base classes

Good rule of thumb: Make the destructor virtual if and only if the class contains at least one virtual function.

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7

CompleteSearch: completesearch/DesignConventions (last edited 2009-05-28 11:52:26 by infao1900)