FAQ 29.05 Can virtual functions be overloaded?

Yes, but it's often easier to use nonvirtual overloads that call nonoverloaded virtuals.

As was discussed in FAQ 29.02, when virtual member functions are overloaded, the hiding rule forces derived classes to do a bit more work than necessary. In these situations, it is often easier if the overloads are nonvirtuals that call virtuals that aren't overloaded. These nonoverloaded virtuals are normally protected:.

The following code shows how to apply this guideline to the situation in the previous FAQ where Base::f(int) and Base::f(float) are overloaded virtuals. These functions are now nonvirtuals that call nonoverloaded virtuals f_i(int) and f_f(float). (Don't redefine nonvirtual member functions; see FAQ 29.02.)

 #include <iostream> using namespace std; class Base { public:   virtual ~Base() throw();   void f(int x)   throw();   void f(float x) throw(); protected:   virtual void f_i(int x)   throw();   virtual void f_f(float x) throw(); }; inline void Base::f(int x) throw()                   <-- 1   { f_i(x); } inline void Base::f(float x) throw()   { f_f(x); } void Base::f_i(int x) throw()                        <-- 2   { cout << "Base::f(int)\n"; } void Base::f_f(float x) throw()   { cout << "Base::f(float)\n"; } Base::~Base() throw()   { } 

(1) Overloaded nonvirtuals

(2) Nonoverloaded virtuals

In class Derived, the behavior of f(int) is changed by overriding Base::f_i(int); redefining f(int) itself would be wrong, since a redefinition would hide Base::f(float).

 class Derived : public Base { public:                                                      <-- 1 protected:   virtual void f_i(int x) throw();                   <-- 2 }; void Derived::f_i(int x) throw()   { cout << "Derived::f(int)\n"; } 

(1) Derived classes never redefine f(int)

(2) Derived classes may override f_i(int)

Now when member function f(int) is invoked on a Derived object, it expands inline as the code of Base::f(int), which calls protected member function f_i(int), and since f_i(int) is virtual, it resolves to the correct member function using dynamic binding (see FAQ 2.24). The message here is that both f(int) and f(float) work correctly on both a Derived& and on a Base&:

 void sample(Base& b, Derived& d) {   b.f(42);   d.f(42);   b.f(3.14f);   d.f(3.14f);                                        <-- 1 } int main() {   Derived d;   sample(d, d); } 

(1) This is not hidden (good!)

The output of this program demonstrates that the behavior depends on the type of the object, not the type of the reference:

 Derived::f(int) Derived::f(int) Base::f(float) Base::f(float) 

This approach is more scalable than the approach presented in the earlier FAQ. It is scalable in two ways, with respect to the code and with respect to the people. With respect to the code, the root of the inheritance hierarchy has a few extra lines of code, but none of the (potentially many) derived classes need have any extra code to handle the hiding rule. This is a good trade-off since an inheritance hierarchy often has many derived classes. With respect to the people, the developer of the root class of the inheritance hierarchy needs to understand the hiding rule, but all the writers of all the derived classes can remain relatively ignorant of it they need to know only that they are to override the virtual member functions rather than the nonvirtual member functions. This is a good trade-off because the developers who build the root classes in the inheritance hierarchies are normally more sophisticated than the developers who build the derived classes.

Note that this approach does not imply any performance overhead, since the overloaded public: member functions are normally inline nonvirtuals.

As before, this guideline applies only to public inheritance; hiding base class member functions is fine for private or protected inheritance (see FAQ 37.01).



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