[Home]  [Edit this page]  [Recent Changes]  [Special Pages]  [Help
CppInheritance

(C++) Inheritance

When a class is a derived class, it inherits the methods of its base class used to mimic a 'IS-A' relationship between classes.

Prefer composition to inheritance [1].

In the example below, there is a base class called Base, having a method to say hello. It has a derived class called Derived, having a method to say bye. The derived class inherits the method to say hello:

  1. include <iostream>
class Base { public: Base() {} void sayHello() const { std::cout << "Hello!" << std::endl; } }; class Derived : public Base { public: Derived() {} void sayBye() const { std::cout << "Bye!" << std::endl; } } int main(int argc, char* argv[]) { Base b; b.sayHello(); Derived d; d.sayHello(); //Inherited from Base d.sayBye(); return 0; }


Inheritance and function calls

In this code I show functions taking base and derived classes as an argument and I comment out the ones not possible. I also show when you can do an upcast or downcast. The first example uses plain pointers, the second smart pointers:

Example #1 using plain pointers

  1. include <iostream>
//--------------------------------------------------------------------------- struct Base { Base(const int& value) : mValueBase(value) {} virtual void doCout() const { std::cout << "Base: " << mValueBase << std::endl; } const int mValueBase; }; //--------------------------------------------------------------------------- struct Derived : public Base { Derived(const int& value1, const int& value2) : Base(value1), mValueDerived(value2) {} virtual void doCout() const { std::cout << "Derived: " << mValueBase << " " << mValueDerived << std::endl; } const int mValueDerived; }; //--------------------------------------------------------------------------- void funcBase(const Base * base) { //Does nothing std::cout << "funcBase called for Base with value " << base->mValueBase << std::endl; base; } //--------------------------------------------------------------------------- void funcDerived(const Derived * derived) { //Does nothing std::cout << "funcDerived called for Derived with values " << derived->mValueBase << " and " << derived->mValueDerived << std::endl; derived; } //--------------------------------------------------------------------------- int main(int argc, char* argv[]) { const Base * base = new Base(0); const Derived * derived = new Derived(1,2); const Base * poly = new Derived(3,4); funcBase(base); funcBase(derived); //Works by upcast funcBase(poly); //Works by upcast //funcDerived(base); //Does not work: Cannot convert 'const Base *' to 'const Derived *' //funcDerived(dynamic_cast<const Derived*>(base)); //ERROR!!! Cannot upcast Base funcDerived(derived); //funcDerived(poly); //Does not work: Cannot convert 'const Base *' to 'const Derived *' funcDerived(dynamic_cast<const Derived*>(poly)); //Works after downcasting with dynamic cast delete base; delete derived; delete poly; return 0; }


Example #2 using smart pointers

Upcasting smart pointers is tough! downcasting is not possible (to the best of my knowledge), so I use a plain pointer:

  1. include <iostream>
  2. include <boost/weak_ptr.hpp>
  3. include <boost/shared_ptr.hpp>
  4. include <boost/intrusive_ptr.hpp>
void funcBase(const boost::shared_ptr<Base> & base) { //Does nothing std::cout << "funcBase called for Base with value " << base->mValueBase << std::endl; base; } //--------------------------------------------------------------------------- void funcDerived(const boost::shared_ptr<Derived> & derived) { //Does nothing std::cout << "funcDerived for boost::shared_ptr called for Derived with values " << derived->mValueBase << " and " << derived->mValueDerived << std::endl; derived; } //--------------------------------------------------------------------------- void funcDerived(const Derived * derived) { //Does nothing std::cout << "funcDerived for plain pointer called for Derived with values " << derived->mValueBase << " and " << derived->mValueDerived << std::endl; derived; } //--------------------------------------------------------------------------- int main(int argc, char* argv[]) { boost::shared_ptr<Base> base(new Base(0)); boost::shared_ptr<Derived> derived(new Derived(1,2)); boost::shared_ptr<Base> poly(new Derived(3,4)); funcBase(base); funcBase(boost::shared_ptr<Base>(boost::weak_ptr<Base>(derived).lock())); funcBase(poly); //funcDerived(base); //[C++ Error] shared_ptr.hpp(162): E2034 Cannot convert 'Base * const' to 'Derived *' //funcDerived(dynamic_cast<Derived*>(base.get())); //ERROR!! Cannot downcast a Base class funcDerived(derived); //funcDerived(poly); //[C++ Error] shared_ptr.hpp(162): E2034 Cannot convert 'Base * const' to 'Derived *' funcDerived(dynamic_cast<Derived*>(poly.get())); //Possible downcast after obtaining the plain pointer return 0; }


Topic links

Code links

Reference

1) Herb Sutter and Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Chapter 34: 'Prefer composition to inheritance'.

last edited (November 15, 2006) by bilderbikkel, Number of views: 3439, Current Rev: 10 (Diff)

[Edit this page]  [Page history]  [What links here]  [Discuss this topic]  [Printer Friendly]  

Members

Username:

Password:


Register
Forgot Password?




Programmers Heaven - for .NET, Java, C/C++ and WEB Developers!
© 1996-2008 Community Networks Ltd. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Development by Tore Nestenius at .NET Consultant - Synchron Data.