PDA

View Full Version : Working with derived classes (Inheritance)



sypher
11-16-2011, 04:24 PM
Class Inheritance - Adding structure to your code


1. Sample polymorphic class (declaration only):

Class CAnimal {
private:
// Variables n' stuff
char* m_animalName; // Name of this beast
unsigned int m_totalFoodConsumedWt; // Total weight of all consumed food since creation

public:
virtual int doSomething();
virtual int makeSound();
bool getBloodPressure(RECT &m_bPressure); // Store B.P. data in rect structure
unsigned int Eat(); // Have animal eat, return weight of food consumed
unsigned int Poop(); // Have animal take a shit, return weight of feces.
unsigned int getName(char* m_pName); // Provide pointer to string where we can put the animal's name
unsigned int getFoodWt(); // Return weight of food
void setName(char* m_aName); // For renaming
public:
CAnimal();
CAnimal(char* m_aName);
virtual ~CAnimal();
};

class CDog : public CAnimal {
public:
CDog();
CDog(char* m_dgName);
public:
virtual int doSomething(); // Override superclass to implement more animal-specific behavior
virtual int makeSound(); /* Override superclass to change sound that is made from this func.
All animals make different sounds, so it is important differentiate between them
*/
bool Beg(unsigned int m_howLong); // Return true if begging was successful and food was recieved
bool attemptStealFood(unsigned int m_numTries); // Return true if food was stolen
};

2. Derived polymorphic classes - Why?


Creating a base class and subclasses to inherit the base is not hard at all, though for someone who is new to C++ it may look alittle daunting. I personally avoided these for awhile. I don't know why, I understood how to do it I just didn't like the idea of wrapping every little thing into an object. But thats neither hear nor there. Polymorphic classes are an excellent way to provide extensibility to a project uses several classes of similar functionality. Sometimes, such as programming user interfaces, you will have two objects that basically do the same thing, but each one has one or two member functions that do it alittle different, based on the purpose of the class.

For example:
Say you have two window classes, such as CAboutDialog and CVersion dialog. Lets also say that each class implements the same basic dialog - one with an OK button and a Static control for displaying text. But what if you want the version dialog to use a textbox for the version information, maybe because there is alot of text to display. It is better to let them scroll through it, instead of displaying a massive screen-filling window. Rather than create 2 classes, each implementing all the code to create/manage a dialog, when the only difference is 1 control and the text content, we can can apply polymorphism to simplify this code.



1. Create a base class that provides basic window functionality. This would be a class that can work with any window. In this case, its named CWindow.

2. Take the two classes and add : public CWindow to the declaration, so it looks like this: CAboutDialog : public CWindow { ... }

3. Implement all generic window functions in the base class, and in the subclasses, leave only functions specific to their purpose that need to be customized. (such as .Create( ... ) or .Show( ... ) - Whatever you would name the function that creates your window.

4. Inside the base class, any functions you want to be able to override, declare a virtual member by placing virtual in the prototype. Example: virtual int getValue()

5. Inside each subclass declaration, any member you are overriding (that allows it), also declare virtual, as it would appear in the base class. This is to let the compiler know we are going to implement our own version of this member function.

6. Implement your functionality using the method described & shown above.


2. What does virtual mean??!?


You may be wondering, what exactly are virtual members? Virtual members are the driving force behind the idea of polymorphism. By declaring a member function as 'virtual', you can then override the function in subclasses so that when it is called in the subclass, the subclass's own function executes instead of the base class version. If you choose not to inherit a function, the base class version of the function will automatically be called instead.

Declaring virtual(s):


virtual unsigned int getStatement();


virtual comes in different flavors though! A member can be declared as a 'pure' virtual member, which means that it requires subclasses to implement their own versions of it, as there is no base class version. This serves to act as a template for classes with similar functionality. These are called abstract classes. A pure virtual member is declared by adding = 0 to the end, before the semicolon but after the prototype declaration.

Pure virtual member


virtual unsigned int getStatement() = 0;



3. Finally, I will go over the featured base/subclass example I posted at the beginning of this tutorial.


Define class name


class CAnimal {



Define members, most cannot be overrided, however, members marked as virtual can be implemented differently in subclasses.


virtual int doSomething();
virtual int makeSound();


Basic member functions, does not allow overrides


bool getBloodPressure(RECT &m_bPressure); // Store B.P. data in rect structure
unsigned int Eat(); // Have animal eat, return weight of food consumed
unsigned int Poop(); // Have animal take a shit, return weight of feces.

The difference between this and the previous code sample? These functions are your standard class functions, functionality is inherently static. the 'virtual' members can be defined and implemented in the base class, as well as the subclass. Each class can implement it differently, as to cater to their own specific needs. However, this cannot be done if it is a pure virtual member. Like I stated before, pure virtual members serve only as a template for other classes of similar functionality.

Defining a derived class


class CDog : public CAnimal {

CDog is the class name, and to inherit the base class ( CAnimal ), we add the following after the class name: : public CAnimal. simply : CAnimal will also work, depending on how you want to work access control.
By adding that code to the end of the class name, we are telling the compiler we want to inherit from : <classname>. In order to be able to override the base class functions though, we need to define the functions we want to override as they are defined in the base class - This is to let the compiler know we intend on providing our own versions of said function( s ).



To conclude ...



Just to clear up any confusion...


public:

my excessive use of the 'public' and 'private' keywords is simply to organize & group the class members based on their type (variable or function / etc), and on their purpose (all eating-related functions go together, where shit functions are grouped somewhere else).. I feel this makes it easier to read, instead of a compacted list of a few dozen class member declarations, scattered around like someone set off a bomb in the middle of a nicely designed class.



Other than the above, there isn't much else to it. The subclass can now use the functions provided in the base class, and override members you need to extend functionality to.

Thats the jist of it though! I wrote this in a rush so I know its by far not the best tutorial out there, but it covers the basics. Also, code was not tested as I just wrote it in the New Thread box, but should work out fine.

Hope ya'll learned something! Until next time..


- sypher

scorpion
11-23-2011, 09:35 PM
great article / contribution! 'animal' is a great example that helps ppl understand OO design.

longestdrive
09-10-2012, 04:32 AM
nice explanations - thanks

webjdeveloper
02-25-2013, 06:24 AM
nice thanks for this

webjdeveloper
02-25-2013, 06:26 AM
nice this is good... thanks...

ERasER
11-09-2014, 04:43 PM
way to create a virtual life form and morphing? cool idea. way to be Sypher...