For those wishing to delve into the world of OOP using C++. You should have a little bit of programming experience to get the most from this tutorial.
–OOP (Object Orientated Programming/Paradigm)–
I’ve heard a couple of people mention that they’d like to see a C++ tutorial that explained more about the OOP side of the language. After all, you can do nearly everything in C that you can do with C++ if you don’t hit on the OOP areas. C has no bool type amongst the non OOP dis-simarlarities.
I recently put out a tutorial on how OOP linked lists work and I was thinking that people with no experience in OOP would not get much value from that tutorial. So I am writing this one!
I won’t cover every detail and built in functionality of the C++ language as there are really good books for that. This is simply an intro to the concepts and syntax, and hopefully it gets you thinking about the possibilities of the language.
So, who should read this tutorial? Well, it’s not an intro the C language. It’s an intro to C++ and the associated syntax as mentioned. There are good tutorials on this website that will bring you up to speed on C. What I am trying to say is that C++ is built using most of the syntax of C, with various other language artifacts thrown in on top of C. This tutorial picks up from where C ends really. You’ll get the picture… Just read on!
A Class of Objects
It’s hard to come up with original analogies. Animals are good to use for C++, as are Cars and Televisions, but I’ll use something that I don’t think has been used before…The Computer.
That’s correct. I think it’s the best example of an OOP analogy that I can think of, in a kind of ironic way.
You know we are working with objects, because that’s part of the OOP acronym. And, you have heard the term class before, I am guessing. So let’s begin the explanation of C++ OOP…
In a procedural language like C, you have to describe problems with the method of solving the problem, firmly in your mind. The method of solving the problem is with a computer program and computers like their programs to be nice and relational to themselves. It’s sometimes hard to juggle your problem solving skills and play nice with the computer at the same time. You can get away with not knowing much about the hardware, but there comes a time when you need to treat some programs in a special way that either the Operating System or the compiler demand. This is not good. You should not have to worry about these things. You should only have to worry about the problem you are attempting to solve, that way you will solve the problem better!
We can do this with classes. Sure, you say, but I prefer to read tutorials rather than go to school.. Not those type of classes! I’m talking about the ones where you can give the computer a blueprint for the production of your new tool. It’s a super tool, it can do anything you like, and once you have built one, you can organise a whole toolbox full of them.
The thing with OOP is that you are still using machine instructions to tell the CPU and some peripherals what to do. You always will have to do it this way! The compiler helps you tell the CPU which machine instructions you want to use, but in the end, the CPU does not understand OOP, C++, APL or how to play an MP3!
It’s time consuming and error prone to organise a list of machine instructions, place them in memory and execute them… So of course, we invented high level languages(HLL). We get the compiler to sort out our source code into machine code which is nothing more than a pattern of bits that tickle the CPU in certain ways. The CPU greedily eats up these machine codes according to which one his/her instruction pointer falls on. But enough of machine code. That’s not what I want to talk about. I want to explain OOP and C++. So, let’s get started.
Nick? Show Us Some Code…
We are surrounded by object orientated design! Really. Take just about anything you use in your day to day life and think of what it would take to manufacture that item yourself. Hmm.. Let’s see…
A television? It has a brand name on it, but do you think that the company that makes the television manufactured every peice of that T.V? No way! They’d never get anything out the door if that was the case, or the factory would be so large, they’d need a mono-rail system to get from cathode-ray tubes to buttons…
No. They out-source production requirements to other specialist companies who in turn, probably out-source even further. What we end up with is television. Now… Do you think that when ACME TV’s build a new model, they start with a clean blackboard? No. When they improve upon an older model, do they have to burn the old plans and re-design from the ground up? Nah.
An object is a module of combined code and procedures. That code ends up being machine code, the garden variety. It’s not magic. You have to make functions and you have to make varibles when you work in C++. There is a lot of work, as much as in any non-oop language and it’s still hard to design programs and make them work properly. But.. They said that OOP was the way of the future! They said that all of our programming problems were solved!
Were they lying? No. Most of what they said was true! The functions and varibles and problems I just spoke of are the ingredients for C++. We bake up some nice objects with C++ and it’s those objects that provide the benefits that they spoke of.
In the intro, I mentioned that I would use a Computer as my OOP analogy. A computer is a good example, I think, because it is such a component based entity. Many of the components that combine to provide us with a running computer system can be desribed in C++ terms. I’m going to start describing bits of the computer as objects, and then I’ll provide some code to support my claims.
First up, the keyboard:
Things a keyboard can do:
- Produce scan codes
- Launch programs
- Adjust the speaker volume(some can..)
Things that describe a keyboard:
- Color
- Keyboard Layout
- Special launch/volume adjust keys
- Wireless or plugged in?
Now, in C++ code:
class Keyboard
{
public:
Keyboard(){}
~Keyboard(){}
void SendScanCode(int theCode);
void LaunchProgram(char* theProgramName);
void VolumeAdjust(int amount);
private:
char Color[10];
char Layout[15];
bool HasSpecialKeys;
bool IsWireless;
};
That is a C++ class declaration. It contains the analog of how we described our keyboard in words. I’ll go through and explain all the new C++ syntax right now.
First, we have the keyword class. This states that we are going to declare a class and following is the name of our class. Our class is named Keyboard. Next, we open a curly brace. We need to enclose the whole class declaration within curly braces and the closing one needs the semi colon after it.
Ignore the keywords public and private for now. They are known as access modifiers, and I’ll explain all about ’em quite soon. Everything else is normal C type looking code! See, I told you you still have to do all the work yourself…
This is a real C++ class declaration and it’s missing the definitions of those functions. Let’s see how we can provide those definitions now.
void Keyboard::SendScanCode(int theCode)
{
MrScreen = DoCodeSendingRoutine(theCode);
}
void Keyboard::LaunchProgram(char* theProgramName)
{
MrOsPleaseLaunchThisProgram(theProgramName);
}
void Keyboard::VolumeAdjust(int amount)
{
volume += amount;
}
Now that kind of looks normal, but kind of looks weird right? What’s with those scope resolution operators? If you know what they’re called, why are you asking me??? Oh… Sorry, I put those words in your mouth…
The ‘::’ or, scope resolution operator is used to tell the compiler that we want this function definition to be tied in with the class name preceding the operator. You place the return type first, then the name of the class, the scope resolution operator and finally a normal function definition.
Instantiating and accessing
What we have seen is a class, fully declared and defined. A class does not do much for us. A class is the blueprint for an object. A software object, but nonetheless, an object. Let’s make something with that Keyboard blue print.
Keyboard Qwerty;
Hmm.. We have just made an object! Let’s make it do something.
Keyboard Qwerty;
Querty.SendScanCode(453);
That’s right. We just instantiated an object and made it do something. You simply think of that object in terms of it being the real life keyboard. It’s up to you how you wish to model each object within the class declaration/definition. You need to see some code working in these initial explanations, so type this into your favorite C++ compiler and fire away.
#include <iostream>
using namespace std;
class Keyboard
{
public:
Keyboard(){}
~Keyboard(){}
void SendScanCode(int theCode);
void LaunchProgram(char* theProgramName);
void VolumeAdjust(int amount);
void SetLastScanCode(int sc);
int GetLastScanCodeSent(){ return LSCS; }
private:
char Color[10];
char Layout[15];
bool HasSpecialKeys;
bool IsWireless;
int LSCS;
};
int main(void)
{
Keyboard qwerty;
qwerty.SendScanCode(66);
cout << "Here is the last scan code sent: " << qwerty.GetLastScanCodeSent() << endl;
getchar();
return 0;
}
void Keyboard::SendScanCode(int theCode)
{
//MrScreen = DoCodeSendingRoutine(theCode);
LSCS = theCode;
}
void Keyboard::LaunchProgram(char* theProgramName)
{
//MrOsPleaseLaunchThisProgram(theProgramName);
}
void Keyboard::VolumeAdjust(int amount)
{
/*if(amount > 0)
{
volume += amount;
}
else
volume -= amount;*/
}
void Keyboard::SetLastScanCode(int sc)
{
LSCS = sc;
}
On the next page, we can dissect this code, ok?
Dissection of First OOP
There’s nothing in that one that you haven’t seen before. Well, apart from the using namespace std and #include> iostream <>
stuff. The namespace stuff is not going to be handled in this tutorial. But in a nutshell, you can declare specific boundaries where names can exist and if you tell the compiler that you are working within the ‘scope’ of that namespace, any identical names you work with on the outside of that namespace will not clash. Namespaces are declared almost exactly like classes and you just give a list of all the names you want to scope to that namespace.
The include file is the C++ equivalent to stdio.h.
Let’s not worry about those two things for now. Let’s look at program.
We declare our class, Keyboard outside of any function, including main(). I have placed the function definitions for class Keyboard under the main() function. It can go directly under the declaration if you want, just like C functions. Notice that one of the definitions is straight after the declaration? It was so short, I thought it’s a waste to give it a whole extra part! It also shows some different ways of doing things.
Because GetLastScanCode()
is defined within the curly braces of the Keyboard class declaration, no ‘::’ scope resolution operator is needed. It’s obvious which class this definition belongs to.
The first thing I do in main()
is instantiate an object from our Keyboard class blueprint. This gives us an object that we can use. Now by use, I mean use whatever functions it has attached to it. I can’t do anything with this object that I have not defined in the class. That’s where the hard parts of C++ and OOP design come from. You have to design good blueprints to make useful objects.
For the executable code example, I had to change the original Keyboard class declaration and definition. An object built from the original Keyboard class would not have had an output to show you on the screen.
When the object has been instantiated by declaring it as though Keyboard were any other type or struct
, we can use some of it’s functionality with the dot ‘.’ operator. It’s no different than using an instance of a struct.
First, I call the SendScanCode() function like this:
qwerty.SendScanCode(66)
You need to realise that now, we are not working with the class Keyboard, but an object of ‘type’ Keyboard. The object ‘qwerty’ has all of the variables and functions that we included between the curly braces of the Keyboard class, but it’s an active member of our program. The Keyboard class cannot ‘execute’ any of those functions. You can’t use the plans for the keyboard to send a scan code! You need to build the Keyboard first, then it will work as the plans dictate. That is the single biggest hurdle in OOP I think.
So I have used the object to send a scan code. And quite rightly, the function SendScanCode() sets the variable ‘LSCS’ to whatever was passed in to it from the calling object. Remember, that function is part of the ‘qwerty’ object. The object has bee built from the plans that tell us how to make a Keyboard. We can now use the object, and that includes any of the things that we wrote down in the plans for Keyboards to do.
As if by magic, when we then get the qwerty object to use some more of it’s functionality, it works!
qwerty.GetLastScanCodeSent()
If you are not sure what cout << is, please refer to an introductory C++ text. Just think of it as an easy printf() function for now. (Psst… cout is an object!!!)
As an exercise, touch the tip of your nose with one eye closed. Well done! Now, using that program we just wrote, declare another object of the class Keyboard, and using the SendScanCode() function, send some different data. I want you to keep the other object in the code and print the results for both objects! Try it.
By now, you should be able to see that a class is simply a package. It’s a package of data with functions that describe a real world entity. This is how C++ separates the problem from the means of solving the problem. You design something with C++ code that represents an element of the problem you are trying to solve.
What I have shown you so far is hardly anything of what C++ can do. It’s the VERY simplest example. Next, we are going to improve the Keyboard class and see another important C++ feature.
Construction and Destruction
There was a part of the Keyboard declaration thay I hoped you would not notice. It’s that part that looks like this
Keyboard(){}
~Keyboard(){}
Those are also functions of the Keyboard class. The first one is known as a constructor and the second is known as a destructor. Yes…. The destructor is a very evil function. Just kidding… The job of the constructor is really quite simple and goes along with our mentality of what OOP is all about. It initialises the variables of objects when they are first instantiated. Well, it can do more than that, but at this early stage, think of the constructor as… Um… The constructor??? Yes, that’s it! It’s a really accurate name for this function. The object is constructed. And it gets destructed also. This happens usually when the program ends and the object goes out of scope. But forget about the destructor for now. Let’s see the constructor in action!
#include
using namespace std;
class Keyboard
{
public:
Keyboard(int);
~Keyboard(){}
void SendScanCode(int theCode);
void LaunchProgram(char* theProgramName);
void VolumeAdjust(int amount);
void SetLastScanCode(int sc);
int GetLastScanCodeSent(){ return LSCS; }
private:
char Color[10];
char Layout[15];
bool HasSpecialKeys;
bool IsWireless;
int LSCS;
};
int main(void)
{
Keyboard qwerty(12);
cout << "Here is the newly built object's LSCS value: " << qwerty.GetLastScanCodeSent() << endl;
qwerty.SendScanCode(66);
cout << "Here is the last scan code sent: " << qwerty.GetLastScanCodeSent() << endl;
getchar();
return 0;
}
//constructor definition follows...
Keyboard::Keyboard(int initialLSCS)
{
LSCS = initialLSCS;
}
void Keyboard::SendScanCode(int theCode)
{
//MrScreen = DoCodeSendingRoutine(theCode);
LSCS = theCode;
}
void Keyboard::LaunchProgram(char* theProgramName)
{
//MrOsPleaseLaunchThisProgram(theProgramName);
}
void Keyboard::VolumeAdjust(int amount)
{
/*if(amount > 0)
{
volume += amount;
}
else
volume -= amount;*/
}
void Keyboard::SetLastScanCode(int sc)
{
LSCS = sc;
}
We have in effect, ‘passed along’ some special startup info we would like for the object. Look carefully at how the data is given to the object. Play around with the constructor. Try adding a string instead of an int, see what complaint the compiler comes up with!
That’s all for this super thin intro to C++, and I hope you enjoyed it, but I’d like to leave you with some challenging exercises to cement the stuff you have learnt.
- Add your own function to the Keyboard class that counts how many scan codes have been sent. When 20 have been sent, it will display a message.
- Design your own class. Think of another computer component that you could ‘model’ with C++
- Declare a class to have another class as a variable! This may seem hard to do, but just remember to declare and define both classes. When you have done that, the name of the class can be used anywhere you would use a normal type name like ‘int’ or ‘char’!
- Read the Linked List part II tutorial, and get some ideas of just what can be achieved.
Please remember that this is a Primer, designed to be perused before the OOP Linked List part II tutorial. If enough people want me to, I’ll present another more advanced tutorial dealing with the things that make C++ really powerful. What I have given you here though is the basic syntax. Play around and try things out. Then you will be ready for the stuff that makes C++ a true OOP language.