Coder Profile - Show off your skills, get a coder profile.
 
 
 
[C++] A tour of OOP
Programming
Intro to OOP

Hey guys. Today I will be writing a tutorial on Object Oriented Programming(OOP) in C++. This
will hopefully help someone learn the heart of C++ and will help me reinforce my own knowledge.
The three major concepts of OOP are: encapsulation, inheritance, and polymorphisms. There's a
mouthful! This tutorial will explain all three. Note that this article was originally written for Newgrounds and
can be found there as well. Also note that all the dash characters (------) simply denote indentation.

Encapsulation

Encapsulation in programming refers to the containment of information. In OOP, you want to
create objects that contain information about something in them. This information should be
visible only to that class. This is the basis of encapsulation. In other words, all information in an
object should ONLY be visible to that object, no other object should be able to see them.

Here is an example of a program that does not demonstrate encapsulation:

#include <iostream>
using namespace std;

class NoEncap{

public:
-----int x;

};

int main(){
------NoEncap ob;
------ob.x = 42; //Valid
------cout<< ob.x <<endl; //Valid
------cin.get();
------return 0;
}

In the above example, the instance variable 'x' is declared public by the public label.The public label
means that all variables after this label (in this case only x), will be openly accessible to all other
objects in your program. This is demonstrated in the example. In main, I can access x from ob using
the dot operator. This is not good because I don't want to be able to change the state of my object
(which is determined by those instance variables), without using the object's methods. This is
encapsulation. In OOP I want to encapsulate all variables of an object so that they can only
modified by that object's methods. Here is an example of the same program above, that follows
encapsulation:

#include <iostream>
using namespace std;

class Encap{
-----int x; /*x is now private, because information in classes are private unless specified otherwise*/
public:
-----int getX() { return x; }
-----void setX(int newX) { x = newX; }
};

int main(){
------Encap ob;

------ob.x = 42; //Invalid. Causes an error!
------cout<< ob.x <<endl; //Invalid. Causes an error!

------ob.setX(42); //Valid, while x is declared private, setX and getX are declared public
------cout<< ob.getX() <<endl; //Also valid. getX() is public and therefore accessible outside itself

------cin.get();
------return 0;
}

Notice, now x is declared as a private variable and the two new methods are public. In this way,
I have access to the methods that alter my object's variables, but I don't have direct access to the
variables themselves. Since the x is declared private, only methods from inside the object can
access it. This is why getX() can access x without a problem. private makes information invisible to
everything outside the class.

In a well developed object, the only public methods are those that the programmer needs to alter
the object. The rest should be private. Take this next example. I will make a simple class that takes
two numbers and adds them.

#include <iostream>
using namespace std;

class EncapPlus{
-----int x;
-----int y;
-----//Both x and y are private variables
-----int calculateSum(){ //This is a private method. It can only be called inside the class.
----------return x + y;
-----}

public:
-----void setXY(int newX, int newY){
----------x = newX;
----------y = newY;
-----}

-----int getSum(){
---------- int theSum = calculateSum(); //Allowed because call is made from inside EncapPlus
----------return theSum;
-----}

};

int main(){
-----EncapPlus obj;

-----obj.setXY(4,16);
-----cout<< obj.calculateSum() <<endl; //This line is an error! calculateSum is private!
-----cout<< obj.getSum() <<endl; //Valid because getSum() is public.

-----cin.get();
-----return 0;

}

Notice that calculateSum is private, and therefore can only be called by methods declared within
EncapPlus. The only public methods in this class, are the ones the programmer will use to
manipulate the class. This is the heart of encapsulation

Encapsulation is important because it lets you create easy to use classes. As a programmer, you do
not need to know how the class does what it does. You simply need to know the interface of
the object. By interface, I mean the public methods the programmer will use to manipulate the
object. For instance, in the above example, I would not need to know how given two numbers,
EncapPlus adds two numbers. I would only need to know that if I call getSum(), I will get the sum.
This seems redundant with addition, but let me give you another example. Say I'm making a game
of asteroids. I need to draw a Ship on the screen. I would make a public method called makeShip(). I
would not need to know how the ship is made, I would only need to know that when I call
that interface method, a ship will be made.

Inheritance

Inheritance refers to one object inheriting properties from another object. Inheritance tries to
establish an "is-a" relationship. This is a really easy concept to understand. Let me give you an
example.

An apple is a fruit. A fruit is a food.

Do you see how the relationship goes from most general (food) to most specific (apple). Think of
about it a little more though. A fruit has all the characteristics of a food. In turn, an apple has all
the characteristics of an fruit. Think about this common phrase:
All apples are fruits, but not all fruits are apples.
Since all apples belong to the fruit family, they are all fruits, but not all fruits are apples. Only some
are. I hope that makes sense.

Back to inheritance in C++. When we use inheritance, we try to establish families of relation like
above. For instance, let's say I have an Animal class. All animals have a names and make noises, so
here would be my animal class:


class Animal{
-------string name;
public:
-------string getName(){ return name; }
-------void setName(string newName) { name = newName; }
-------void makeNoise() { cout<<"ANIMAL NOISE!!!!!!"<<endl; }
};

Now lets think about a kind of animal. Felines. This is a family of animals like cats, tigers, lions.
Lets say(for simplicity), that all Felines have everything that animals have + claws. Now we could
write out a new Feline class with containing everything that Animal has, OR we could use
inheritance to inherit the things that Animal and then add claw info. Take this example:


class Feline : public Animal {
------int clawLen;
public:
------int setClawLen(int newClawLen) { clawLen = newClawLen; }
------void scratch() { cout<<"OUCH"; }
};

Note the use of the colon to inherit all the traits of Animal. The public means that all the public
methods of Animal, will become public methods of Feline. Everything private, will remain private.
There is also private and protected specifiers, but they are outside of the scope of this tutorial.
Now Felines all have a name variable (even thought it is not explicitly defined in Feline), methods to
access the name, and a makeNoise() method. Those are the traits that Feline derived(or inherited)
from Animal. Along with those common traits, Feline defines several extra goodies (clawLen).
Note that the Animal class does not have clawLen, setClawLen(int newClawLen), or sratch(). These
are added only for Feline.

The properties (the methods and variables) of Animal were inherited to Feline

Now let's examine two level inheritance. Say that I now need a type of Feline, cat. For simplicity
sake, lets say that a cat can be either an indoor cat or outdoor cat. Here's an example:


class Cat : public Feline{
-----bool indoorCat; //true if the cat is an indoor cat
public:
-----bool isIndoorCat() { return indoorCat; }
-----void setCatStatus(bool newStatus) { indoorCat = newStatus; }
}

In the above case Cat contains all the properies of Animal AND Feline, as well as Cat specific
details (ie, indoorCat)
Note that Feline does not contain anything that Cat defines explicitly
(indoorCat, isIndoorCat(), and setCatStatus() ).
Using C++'s inheritence system, we just developed the following is-a relation:

A cat is a Feline. A Feline is a(n) Animal

This is a class hierarchy. We developed a specific class (Cat), by using properties from more
general classes (Feline, and Animal).
Note that all three classes can be used as objects just like any other class.

Polymorphism

Polymorphism sounds like a hard concept. To simplify it, just think of the following phrase: One
interface, multiple methods. In polymorphisms, we try to create methods that will do something.
These methods will be able to act slightly differently based on what kind of data they are dealing
with, but they are all under the same name. One interface, multiple methods.
C++ supports two types of polymorphism. Compile time and run time. Compile time polymorphism
is accomplished by function overloading. It is not related to OOP, so it will not be talked about in
this article. Run-time polymorphism is based on OOP.

Let's use the previous Cat-Feline-Animal hierarchy as an example of run-time polymorphism. Recall
that Animal had a method called makeNoise(); that outputted "ANIMAL NOISE!!!!!!" to the screen.
Take this following code snippet as an example. Note: all the classes used are those developed
above.

int main(){

-----Animal sexyAnimal;
-----Feline sexyFeline;
-----Cat sexyCat;

-----sexyAnimal.makeNoise();
-----sexyFeline.makeNoise();
-----sexyCat.makeNoise();

-----return 0;
}

The output of the above program would be:


ANIMAL NOISE!!!!!!
ANIMAL NOISE!!!!!!
ANIMAL NOISE!!!!!!

What if I wanted to make it so that Felines and Cat's made thier own noise. How would I do that?
Run-Time Polymorphism bitches. That's how. I can overload makeNoise() when I inherent the
Animal class. By overload, I mean write a new version of makeNoise(). It will have the same name.
To do this, I will need to declare makeNoise() in animal as a Virtual function using the virtual
function. This tells the compiler that makeNoise() will be overloaded in the classes that derive it.
Let's look at the new class Hiearcy:

class Animal{
-------string name;
public:
-------string getName(){ return name; }
-------void setName(string newName) { name = newName; }
-------virtual void makeNoise() { cout<<"ANIMAL NOISE!!!!!!"<<endl; }
};

class Feline : public Animal {
------int clawLen;
public:
-------virtual void makeNoise() { cout<<"FELINE NOISE!!!!!!"<<endl; } //OVERLOAD
------int setClawLen(int newClawLen) { clawLen = newClawLen; }
------void scratch() { cout<<"OUCH"; }
};

class Cat : public Feline{
-----bool indoorCat; //true if the cat is an indoor cat
public:
-------virtual void makeNoise() { cout<<"CAT NOISE!!!!!!"<<endl; } //OVERLOAD
-----bool isIndoorCat() { return indoorCat; }
-----void setCatStatus(bool newStatus) { indoorCat = newStatus; }
}

Now, I have a specific implementation of makeNoise() for each class in my hiearcy. How will the
compiler know which type to call though? Through pointers. More specifically, base-class pointers.
A base class pointer is a pointer the points to an object of type <baseclass>, where baseclass is the
class that is derived from. What is the base class in our case? If you said Animal, you win! lol
Here is an example of a base class pointer:

Animal *basepnt;

Note that a base class pointer can point to any object that is derived from it. In this case, this
means that a pointer of type Animal can point to an object of Feline type and Cat type. For instance,
the following is valid:

-----Animal *basepnt;

-----Animal sexyAnimal;
-----Feline sexyFeline;
-----Cat sexyCat;

-----basepnt = &sexyAnimal;
-----basepnt = &sexyFeline;
-----basepnt = &sexyCat;

Although a baseclass pointer can point to any derived class, a dervied class pointer can not point to
a base class. For example, the following is invalid:

-----Feline *pnt;

-----Animal sexyAnimal;
-----Feline sexyFeline;
-----Cat sexyCat;

-----pnt = &sexyAnimal; //INVALID!
-----pnt = &sexyFeline; //VALID
-----pnt = &sexyCat; //VALID

Note, since Cat is derived from the type of our pointer(Feline), we can point to it. Animal however,
is not deceived from Feline (in fact Feline is derived from Animal), so our Feline type pointer cannot
point to it.

Now back to how the compiler knows what version of makeNoise() to call. The compiler will
determine which version to call based on what the base-class pointer is currently pointing to. Take
this as an example:

int main(){
-----Animal *basepnt;

-----Animal sexyAnimal;
-----Feline sexyFeline;
-----Cat sexyCat;

-----basepnt = &sexyAnimal;
-----basepnt->makeNoise();

-----basepnt = &sexyFeline;
-----basepnt->makeNoise();

-----basepnt = &sexyCat;
-----basepnt->makeNoise();

-----cin.get();
-----return 0;

}

The output from the above program is:


ANIMAL NOISE!!!!!!
FELINE NOISE!!!!!!!
CAT NOISE!!!!!!!!!

Bingo! Exactly what we wanted. We used one interface ( makeNoise() ), to do slightly different
things. That is polymorphism.

The End

Hope this tutorial helps someone. Please give me feedback on how I did. Hopefully I didn't mess
something up. Thanks for your time.


Posted By Cinjection
Please login to rate coding articles.

Click here to register a free account with us.
Comments
Please login to post comments.
Page 1 of 1
More Articles By This Author
Intorduction to memoization.
Strings in C++
Vectors in C++
[C++] Pointers and their practical uses in programming.
The Differences and Similarities Between C and C++
[C++] A tour of OOP
[C++] Templates
Recently Posted "Programming" Articles
[PHP] - Lets kill the complex IF
Java: Obtaining User Input - Part 1
Basic PortScanner in VB6.0
N-Queens-Series Part I (Only the fittest survive)
Currying in JavaScript: Fun for the Whole Family!
[PHP] Create A Unique Page Hits Counter
Actionscript Events
Actionscript API
Quick Threading Tutorial - C++
C++ And Me (A Love Story)
Recently Rated "Programming" Articles
[PHP] - Lets kill the complex IF
Java: Obtaining User Input - Part 1
[C++] Templates
Quick Threading Tutorial - C++
Intorduction to memoization.
N-Queens-Series Part I (Only the fittest survive)
[PHP] Create A Unique Page Hits Counter
Currying in JavaScript: Fun for the Whole Family!
Actionscript Events
First look at C
source codes Categories articles
Browse All
Business & E-Commerce (1)
Databases (1)
Design & Creativity (1)
Internet & Web Sites (1)
Life In General (2)
Networking (1)
Operating Systems (4)
Other (2)
Programming (51)
Security (10)
Software Development (5)
Standards (1)
Web Development (15)
search Search Inside
Programming
 
 
Latest News About Coder Profile
Coder Profile Poll
Do you use RSS feeds?

Yes, all the time, first thing i do on the net
Sometimes, when i remember to check them
No, can't be bothered with them
No, what are they?


please login to cast your vote
and see the results of this poll
Latest Coder Profile Changes
Coder Profile was last updated
5 Days Ago
Official Blog :: Make A Donation :: Credits :: Contact Me
Terms & Conditions :: Privacy Policy :: Documents :: Wallpapers
Version 1.46.00
Copyright © 2007 - 2008, Scott Thompson, All Rights Reserved