FAQ 8.06 Can an overridden virtual function be a no-op?

Only if the base class says it might.

It's proper for an overridden virtual function to do nothing if and only if the specification of the member function in the base class tells users that it might do nothing. Without such a specification in the base class, doing nothing is like false advertising. For example, consider a used-car salesman selling a kind-of car where applying the brakes is a no-op (that is, the brake lines have been cut). Ralph Nader would correctly say that such a vehicle isn't substitutable for a car.

Consider the Ostrich / Bird dilemma. Suppose Bird::fly() promises that the altitude of the Bird will be strictly positive.

 #include <iostream> using namespace std; class Bird { public:   Bird() throw();   virtual ~Bird() throw();   int altitude() const throw();   virtual void fly() throw();     // PROMISE: altitude() will return a number > 0;     // never throws an exception protected:   int altitude_; }; Bird::Bird() throw() : altitude_(0) { } Bird::~Bird() throw() { } int Bird::altitude() const throw() { return altitude_; } void Bird::fly() throw() { altitude_ = 100; } 

Based on this promise, it is appropriate and normal for users to write code such as the following.

 void sample(Bird& bird) throw() {   bird.fly();   if (bird.altitude() <= 0)     cerr << "Error! Call the hotline at 1-800-BAD-BUGS\n"; } 

But suppose Ostrich::fly() is defined as a no-op:

 class Ostrich : public Bird { public:   virtual void fly() throw();     // PROMISE: altitude() will still be zero }; void Ostrich::fly() throw() {   // Does nothing despite what Bird said (bad!) } 

Now suppose someone legitimately passes an Ostrich into the sample() code:

 int main() {   Ostrich bird;   sample(bird); } 

Note that decorating the Ostrich class with a comment ("I can't fly") isn't good enough, since many users won't even be aware that they're dealing with an Ostrich.

Trying to make this safe with a canYouFly() query still breaks existing user code, because calls to bird.fly() need to be patched with a test, "If you can fly, then fly." Note also that these capability queries limit extensibility (see FAQ 27.07).

The lesson is that improper inheritance cannot be fixed by having the overridden function do nothing if the contract of the base class says the function will do something. This is because the root cause of improper inheritance is behavior that violates a contract and doing nothing can violate a contract. Specifically, the behavior of an overridden virtual function that does nothing conflicts with a base class contract that says the member function will do something.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net