C++ Derived Classes by Mike Carns Now that you have a basic handle on OOP we are going to cover the second fundamental idea in OOP. This is the idea of derived classes. Part 1: What are they? Derived classes are classes that are based on another class. They have all the members of the base cass, plus whatever you add to them. For example: class Base { protected: int basething; public: Base( void ); ~Base( void ); void SetBaseMember( int value ); }; Base::SetBaseMember( int value) { this.basething = value; } class Derived : public Base { // format: class : private: int derthing; public: Derived( void ); ~Derived( void ); void SetDerMember( int value ); }; (code for SetDerMember not necessary... same as SetBaseMember) main() { Base myBase; Derived myDerived; Base.SetBaseMember( 4); Derived.SetBaseMember( 5); } Woah!!! there's no SetBaseMember declared in Derived! There doesn't have to be. A derived class inherits everything marked public and protected (we'll cover it in a sec) from its base class! Part 2: Protected access. I'll make this short. Protected access is the same as private, only casses derived from the base class will inherit all protected data members and functions as if they were private. So... if you are going to derive another class from a base class, mark the data mebers you want derived as protected, all others as private. 'nuf said. Part 3: The Derivation Chain and the virtual keyword. Look at the following program and it's output. class Gramps { public: Gramps( void ); ~Gramps( void ); }; Gramps::Gramps( void ) { cout << "I'm in the Gramps constructor\n"; } Gramps::~Gramps( void ) { cout << "I'm in the Gramps destructor\n"; } class Dad: public Gramps { public: Dad( void ); ~Dad( void ); }; Dad::Dad( void ) { cout << "I'm in the Dad constructor\n"; } Dad::~Dad( void ) { cout << "I'm in the Dad destructor\n"; } class Junior : public Dad { .. all code the same as Dad and gramps... no need to type it again. }; main() { Junior * myJunior; myJunior = new Junior; delete myJunior; } // note: we can use auto creation and get the same results, however, for clarity we use manual Output: I'm in the Gramps constructor I'm in the Dad contructor I'm in the Junior constructor I'm in the Junior destructor I'm in the Dad destructor I'm in the Gramps destructor Now why did this happen? All we did was create Junior! Well when you create an object, the system goes down the list and calls the constructor of the ultimate base class, then the class derived off of it, until it gets to the current class. The reverse happens for destruction. Here's how you get around it: class Gramps { virtual Gramps( void ); ... }; The virtual keyword will tell the system that if this is a base class, to skip this function and call the overriding function in the derived class. So if you defined two functions in two classes, one called Shape, the other Called Circle, that looked like this: virtual void Shape::Display() { int result; result = this.length * this.width; cout << result; } (Circle is derived from Shape) void Circle::Display() { const pi = 3.14; int result; result = this.r * this.r * pi; cout << result; } and in main you did this: myCircle.Display(); Shape's Display would not be called due to the virtual keyword. If you haden't added the virtual, Shape's display would have been called, displaying the wrong answer (remember, if height and width had been declared in Shape, they would be inherited by Circle, not causing an error in Shape::Display()). Here's a full exampe program: #include //--------------------------------------- Shape class Shape { // Data members... // Member functions... public: virtual void WhatAmI( void ); }; void Shape::WhatAmI( void ) { cout << "I don't know what kind of shape I am!\n"; } //--------------------------------------- Shape:Rectangle class Rectangle : public Shape { // Data members... // Member functions... public: void WhatAmI( void ); }; void Rectangle::WhatAmI( void ) { cout << "I'm a rectangle!\n"; } //--------------------------------------- Shape:Triangle class Triangle : public Shape { // Data members... // Member functions... public: void WhatAmI( void ); }; void Triangle::WhatAmI( void ) { cout << "I'm a triangle!\n"; } //--------------------------------------- main() void main( void ) { Shape *s1, *s2, *s3; s1 = new Rectangle; s2 = new Triangle; s3 = new Shape; s1->WhatAmI(); s2->WhatAmI(); s3->WhatAmI(); } Well now you have mastered the meat and potatoes of OOP! So go out there are derive something!!!