Expanding the class

6 minute read

This article is part 3 in a series: C++ introduction



A class is quite useless if it does nothing, in our case it really does nothing at all.
We create a instance of it, but we never use it, and there is no real way of actually using the object in its current state.
So lets make it useful!

In C++, most classes have two files, one for declaration (called a header file, usually of the file type .h) and one for definition (commonly of the file type .cpp).
So, to make our class more “genuine”, we split it up into two files.

 // This is our Person.h file, our declaration of the class Person.
#ifndef PERSON_H
#define PERSON_H

class Person
{
    public:
        Person();
        Person(const string& name);
        Person(const Person& copy);
        ~Person();

        void SetName(const string& name);
        const string& GetName();
    private:
        string myName;
}
#endif //PERSON_H
 // This is our Person.cpp file, our definition of the class Person.
#include "Person.h"

Person::Person() {
    myName = "Jane Doe";
}

Person::Person(const string& name) {
    myName = name;
}

Person::Person(const Person& copy) {
    myName = copy.myName;
}

Person::~Person() {
}

void Person::SetName(const string& name){
    myName = name;
}

const string& Person::GetName() {
    return myName;
}

Now we have a .h file, our header, as you see, none of the functions in the class are implemented in the header file (inline and templates will be explained in later posts).
The class implementation is done in the .cpp file.

The first thing you might notice is the #ifndef, #define and #endif things.
Those are called “header guards”. The #define <name> defines a value, while the #ifndef checks if the value exists. So, if the value already exists, the compiler will not parse the file twice. The #endif is just like the ending bracket of a if statement, the end of the if.

A few things have also been added to the class, a private access specifier and under that one, a string which is named myName. There are also three new functions in the public parts of the class, a new constructor, a GetName function and a SetName function.

The new constructor takes one argument, a const reference to a string named name.
When a passed value is set to be const (constant) it means that it will not change within the function. There are ways to get past this, but it would break the contract and thats not okay in my opinion!
When the & sign is suffixed to the type (or prefixed to the name or even in the middle), it means that it is a reference. References will be explained more in depth in a later post, but in short it means that it’s not a copy of the variable that is passed in, but rather the value itself, using references of objects is a way of using less memory than creating copies in every function call.

The GetName function returns a constant reference to a string, and the SetName function takes a constant reference to a string.

We also have a cpp file, the file where the class is implemented.
The first thing done in the cpp file is to include the header file with #include. After including the header, we can implement its functions.
Each function we declare is prefixed with the class name, for example, the default constructor is written Person::Person.
This is so that the compiler knows that we are implementing a class function (or member function or even a method in some termonoligy), and not a global function.

We start by implement the default constructor. In this one, I have chosen to set the name of the Person to Jane Doe. So whenever a new instance of the object is created, it will be named Jane Doe until another name have been set.
After the default constructor another constructor is implemented, this is a constructor which takes the name of the person. That means, if the person object is initialized with this constructor, it will have the name passed into it from start.
After that, the copy-constructor is implemented. A copy-constructor always copies the values of the object passed in. In this classes case, the name, cause that is the only thing that we actually store in the class.
Nothing is done in the destructor, cause we got no memory to release.

After the constructors and destructor are done, the implementation of the SetName method comes. It takes a constant reference to a string as an argument which is set to the private myName member variable.
The method can be used to change the name of the person.

The last function to be implemented is the GetName method.
This function returns a constant string reference. The referenced object that it returns is the myName member, we make it const, cause we don’t want it to change outside of the class, and we make it a reference cause its cheaper to pass.

Inside a class, everything in the class is possible to reach. All public and private members are accessible in the classes own functions.
Outside of the class, the private (and protected) members are unreachable. This means that calling person.myName will produce a compiler error. And that’s one of the reasons why we create a get and a set accessor.
Getters and Setters are not always needed, if the variable is not supposed to be reached outside of the class itself, accessors are useless. And as always, never write functions that you have no use of. You could also just need one of them, getting a persons name is not too hard in real life, setting it though, might be harder. Would be weird if we could run around and change peoples names however we wanted eh?
You could also make the myName variable public, thus reach it from outside. But I would not recommend this, variables should be private (if not const) and should be accessed through accessors only. One good thing which comes from this is that you always know where the variable is changed, and you could even set a breakpoint in the accessor.

So how do we use the class?
Well, let me show you a very simple example!

#include "Person.h" // Includes the person class.

int main() {
    Person meg;
    Person chris;
    meg.SetName("Meg Griffin");
    chris.SetName("Chris Griffin");
    std::cout << meg.GetName() << " and " << chris.GetName() << " are two characters in the show Family Guy" << std::endl;
    return 0;
}

What is done above?
Two Person objects are created, meg and chris, their names are then set via the set-accessor (SetName). After the names are set, output is made, which uses the classes get-accessor to fetch the names of the persons (GetName).

Output: Meg Griffin and Chris Griffin are two characters in the show Family Guy

So, what’s the difference between a class and a struct (in c++)?
Well, its quite easy, inside a class, everything is by default private, that means, if public: is not added in the header, everything in the class will be private. While a struct is the opposite, I.E., by default public.

This post have been moved from the old blog.
Original publish date is Feb 7 2015.