Get up to 80 % extra points for free! More info:

Lesson 2 - First OOP application in C++ - Hello object world

At the beginning of the Basic C++ constructs course we created a Hello world program. Let's do a similar program as an introduction to object-oriented programming. We'll program Hello object world!

Creating a project

First, we'll create a new project (console application). You can see how to create the project in the screenshots below.

Creating a new C++ project - Object-Oriented Programming in C++

We create the project as a classic empty application. Then we click on OK:

Project properties - Object-Oriented Programming in C++

In the project, we'll create a new main.cpp file. We'll do it by right-clicking the project in Solution Explorer and choosing Add -> New Item:

Adding a new file to the C++ project - Object-Oriented Programming in C++

Then we select the .cpp file:

File type - Object-Oriented Programming in C++

In this file, we'll will insert the basic C++ application structure as we have been used to:

#include <iostream>

using namespace std;

int main()
{
    return 0;
}

In Solution Explorer, we'll right-click the Source files folder and select Add -> Class:

Adding a class to the C++ project - Object-Oriented Programming in C++

In the window that appears, we'll click on C++ Class. Then a next window is displayed, in which we fill in the names as shown. These are names of the class files that will represent a pattern to create objects which can greet:

Setting C++ class properties - Object-Oriented Programming in C++

Visual Studio creates two files for us: Zdravic.h (there will be the class itself) and Zdravic.cpp (where the function definitions will be). The division of the class into these two files is necessary - see C and C++ compilation lessons. We'll rewrite the contents of the files to:

Greeter.h

#ifndef __GREETER_H__
#define __GREEER_H__

class Greeter
{

};

#endif

Greeter.cpp

#include "Greeter.h"

The preprocessor directives (#ifndef,#define, and #endif) ensure that the file is included only once. By default, Visual Studio uses the #pragma once directive, but this one is more practical for us (it works even when compiling on Linux). The originally generated Greeter(void) and ~Greeter(void) functions were a constructor and a destructor that we'll look at in the next lesson.

Method declaration

When we'll use this class, we'll want it to do something. That's why we're going to provide some methods in the Greeter class. In C++, we write methods the same as functions:

Greeter.h

#ifndef __GREETER_H__
#define __GREETER_H__

class Greeter
{
public:
    void greet();
};

#endif

Greeter.cpp

#include <iostream>
#include "Greeter.h"

using namespace std;

void Greeter::greet(void)
{
    cout << "Hello object world!";
}

We must declare the method twice, once as a header in the .h file and once with the body in the .cpp file. Here we have finished for now, let's move to main.cpp.

Creating a class instance

Now, we're goint to create a Greeter instance in the body of the main() method. But first we have to say that we want to use our Greeter class, which we've just created. We do this by including our class in the main.cpp file using #include "Greeter.h". Unlike classic include (for example of iostream), you may notice replacing angle brackets with quotes. If we use brackets, the compiler searches for the file in its paths (typically library paths). If we use quotes, the compiler will use the relative path (the current project folder in our case).

We store objects in variables, the class name is used as the data type (same as int, for example). We'll declare a variable and then create a new instance of Greeter in it:

#include <iostream>
#include "Greeter.h"

using namespace std;

int main()
{
    Greeter _greeter;
    return 0;
}

This creates a variable _greeter. We can also create an instance as follows:

Greeter* _greeter = new Greeter();

[here]

This approach creates an instance dynamically and it's stored on the heap. We'll return to it in more advanced parts of our C++ course.

Calling the method

And because we already have our first object (instance), we can call its method. At the end of the code (before return 0;), we'll add cin.get() (so that the program doesn't end immediately and wait for any key to be pressed). Finally, the main.cpp file looks like this:

main.cpp

#include <iostream>
#include "Greeter.h"

using namespace std;

int main()
{
    Greeter _greeter;
    _greeter.greet();
    cin.get();
    return 0;
}

Now we can run the program. The output will be as follows:

Console application
Hello object world!

So we have our first object-oriented application! The logic is performed by a corresponding object. When we write larger applications, we'll appreciate such decomposition of functions into individual objects since the resulting application is very clear.

Method parameters

Now let's give our greeting() method a name parameter to greet a particular user:

Greeting.h

#ifndef __GREETER_H__
#define __GREETER_H__
#include <string>

using namespace std;

class Greeter
{
public:
    void greet(string name);
};

#endif

Greeter.cpp

#include <iostream>
#include "Greeter.h"

using namespace std;

void Greeter::greet(string name)
{
    cout << "Hi " << name << endl;
}

Now let's update our main() function:

Greeter _greeter;
_greeter.greet("Carl");
_greeter.greet("Peter");

And after running the application, we get the following output:

Console application
Hi Carl
Hi Peter

Class attributes

Let's add some field (variable) to the class, e.g. a text where the greeting will be stored. From the previous lesson, we already know that classes contain functions and data. We declare data parts of classes the same as variables. Here's what our class should look like at this point.

Greeter.h

We declare the field in the header file:

class Greeter
{
public:
    string text;
    void greet(string name);
};

Now all Greeter instances store their text.

Greeter.cpp

We'll edit the greeting() method to greet using the text in the text field:

void Greeter::greet(string name)
{
    cout << text << " " << name << endl;
}

main.cpp

Now we need to set up the instance we created in main.cpp for the first time:

Greeter _greeter;
_greeter.text = "Hi";
_greeter.greet("Carl");
_greeter.greet("Peter");
_greeter.text = "Hello programmer";
_greeter.greet("Richard");

And the application's output:

Console application
Hi Carl
Hi Peter
Hello programmer Richard

Method return value

In object-oriented design, it's not recommended to let each object control the input and output, i.e. printing lots of stuff into the console. Each object should have a single responsibility and shouldn't exceed its purpose. Let's make our object solely responsible for creating the greeting text, and we'll move the printing outside the object, i.e. to the main() method. The advantage to designing objects with a single responsibility is that they're then universal and reusable. Our object can only print text to the console now, but we'll change it so the method will only return the text and it'll be up to the recipient to decide what to do with it. Like this we could store greetings into files, print them on websites or process them further.

Since we want the method to return a string value, we change its void type to string. To return a value, we use the return command. Let's edit the class code:

Greeter.h

class Greeter
{
public:
    string text;
    string greet(string name);
};

Greeter.cpp

And so is the implementation:

string Greeter::greet(string name)
{
    return text + " " + name + "!\n";
}

main.cpp

To do this, we need to edit the main.cpp file:

int main()
{
    Greeter _greeter;
    _greeter.text = "Hi";
    cout << _greeter.greet("Carl");
    cout << _greeter.greet("Peter");
    _greeter.text = "Hello programmer";
    cout << _greeter.greet("Richard");
    cin.get();
    return 0;
}

Our code now meets best practices. The source codes are included below the article. You can try the whole program here or in the attached project.

int main()
{
    Greeter _greeter;
    _greeter.text = "Hi";
    cout << _greeter.greet("Carl");
    cout << _greeter.greet("Peter");
    _greeter.text = "Hello programmer";
    cout << _greeter.greet("Richard");
    cin.get();
    return 0;
}
#ifndef __GREETER_H__
#define __GREEER_H__
#include <string>

using namespace std;

class Greeter
{
public:
    string text;
    string greet(string name);
};

#endif
#include <iostream>
#include "Greeter.h"

string Greeter::greet(string name)
{
    return text + " " + name + "!\n";
}

Great! Our program already has some quality to it, despite it being relatively useless. If you want, you can try to create an object-oriented remake of our console calculator. Next time, A RollingDie in C++ and Constructors, we'll take a closer look at the promised constructors and destructors.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 11x (386.16 kB)
Application includes source codes in language C++

 

Previous article
Introduction to object-oriented programming in C++
All articles in this section
Object-Oriented Programming in C++
Skip article
(not recommended)
A RollingDie in C++ and Constructors
Article has been written for you by David Capka Hartinger
Avatar
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities