Object-Oriented Programming in C++

It has been a long time since I didn't write an article. Now, let me continue to write more for C++. I wrote about the crash course in C and C++. In this article, I wrote about Object-Oriented Programming in C++.

It is easy to apply OOP in C++ because of the language itself. In other words, C++ is a version of C but with an OOP feature. There is no "interface" in C++ that may cause you to be confused because that can be achieved by "class" only. Let's code!

Abstraction

Properties

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

using namespace std;

class Animal {
    public:
        string name;
        int feets;
        bool hasPaws;
};

int main() {
    Animal cat;

    cat.name = "Cat";
    cat.feets = 4;
    cat.hasPaws = false;

    cout << cat.name << " has " << cat.feets << " feets." << endl;
    if (cat.hasPaws) {
        cout << cat.name << " has paws." << endl;
    }

    Animal dog;

    dog.name = "Dog";
    dog.feets = 4;
    dog.hasPaws = true;

    cout << dog.name << " has " << dog.feets << " feets." << endl;
    if (dog.hasPaws) {
        cout << dog.name << " has paws." << endl;
    }

    return 0;
}

Let's start with creating a class with its properties. In coding a class of C++, defining an access modifier is a must. We can start with the public. We let those properties be accessible to the public.

Let's compile and run it with the command g++ main.cpp -o main && ./main. You can see more explanations about the basic syntaxes on the C/C++ Crash Course.

Methods

We did repetition while printing. Let's create a method for it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

using namespace std;

class Animal {
    public:
        string name;
        int feets;
        bool hasPaws;

        void print() {
            cout << name << " has " << feets << " feets." << endl;
            if (hasPaws) {
                cout << name << " has paws." << endl;
            }
        }
};

int main() {
    Animal cat;

    cat.name = "Cat";
    cat.feets = 4;
    cat.hasPaws = false;

    cat.print();

    Animal dog;

    dog.name = "Dog";
    dog.feets = 4;
    dog.hasPaws = true;

    dog.print();
}

Inheritance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

class Animal {
    public:
        string name;
        int feets;
        bool hasPaws;

        void print() {
            cout << name << " has " << feets << " feets." << endl;
            if (hasPaws) {
                cout << name << " has paws." << endl;
            }
        }
};

class Monster: public Animal {
    public:
        vector<string> abilities;
};

class Legend {
    public:
        string myth;
};

class Mythical: public Monster, public Legend {
    public:
        string story;
};

int main() {
    Mythical dragon;

    dragon.name = "Dragon";
    dragon.feets = 4;
    dragon.hasPaws = true;
    dragon.abilities.push_back("Nuclear blast");
    dragon.abilities.push_back("Ice smoke");
    dragon.myth = "Appears in the folklore.";
    dragon.story = "From the hidden world.";

    dragon.print();

    return 0;
}

C++ is cool. It supports multiple inheritance. From the example above, we create a dragon from Mythical and that dragon has all the properties from its parents.

We can define the abilities like this, dragon.abilities = {"Nuclear blast", "Ice smoke"}. But we need at least a C++11 compiler to compile it, g++ -std=c++11 main.cpp -o main && ./main.

Virtual Class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

using namespace std;

class Animal {
    public:
        string description;
};

class Monster: public Animal {

};

class Legend: public Animal {

};

class Mythical: public Monster, public Legend {

};

int main() {
    Mythical dragon;

    dragon.description = "This should be ambiguous.";

    return 0;
}

Could you compile the code above and see what you get? That error is an error of ambiguity. The compiler didn't know where she got the description.

To solve that, let's make the classes derived from virtual classes.

We added virtual syntax to the parent class. Now, the ambiguity is solved.

Abstract Class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

using namespace std;

class Animal {
    public:
        void print();
};

class Monster: public Animal {

};

class Mythical: public Animal {
    public:
        void print() {
            cout << "Mythical is a part of animal." << endl;
        }
};

int main() {
    Monster monster;
    Mythical mythical;

    monster.print();
    mythical.print();

    return 0;
}

Let's compile the code above and what will you get? That is an error of an undefined symbol. What's wrong? That is because the Animal is an abstract class. On line 7, we can see a print method without the implementation, which means the children from that class should implement the print method.

Of course, we need to write the implementation of the print method to solve that.

Polymorphism

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>

using namespace std;

class Animal {
    public:
        string name;
        int feets;
        bool hasPaws;

        void print() {
            cout << name << " has " << feets << " feets." << endl;
            if (hasPaws) {
                cout << name << " has paws." << endl;
            }
        }
};

class Monster: public Animal {
    public:
        vector<string> abilities;

        void print() {
            cout << name << " is a monster!!!" << endl;
            cout << name << " has:" << endl;

            for (string ability : abilities) {
                cout << "- " << ability << endl;
            }
        }
};

int main() {
    Monster dragon;

    dragon.name = "Dragon";
    dragon.feets = 4;
    dragon.hasPaws = true;
    dragon.abilities.push_back("Nuclear blast");
    dragon.abilities.push_back("Ice smoke");

    dragon.print();

    return 0;
}

Let's try to remove the print method from the Monster class. We will get no error. Because the Animal, the parent of the Monster, already has the print method.

The example above is about Polymorphism. The children replace the details of the parent methods.

Encapsulation

Interface

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
#include <iostream>

using namespace std;

class Properties {
    public:
        virtual void setName(string name) = 0;
        virtual string getName() = 0;
        virtual void setFeets(int feets) = 0;
        virtual int getFeets() = 0;
        virtual void setHasPaws(bool hasPaws) = 0;
        virtual bool getHasPaws() = 0;
};

class Animal: public Properties {
    public:
        string name;
        int feets;
        bool hasPaws;

        void setName(string name) {
            this->name = name;
        }

        string getName() {
            return name;
        }

        void setFeet(int feets) {
            this->feets = feets;
        }

        int getFeet() {
            return feets;
        }

        void setHasPaws(bool hasPaws) {
            this->hasPaws = hasPaws;
        }

        bool getHasPaws() {
            return hasPaws;
        }

        void print() {
            cout << name << " has " << feets << " feets." << endl;
            if (hasPaws) {
                cout << name << " has paws." << endl;
            }
        }
};

class Monster: public Animal {
    public:
        vector<string> abilities;

        void setName(string name) override {
            this->name = name;
        }

        string getName() override {
            return name;
        }

        void setFeets(int feets) override {
            this->feets = feets;
        }

        int getFeets() override {
            return feets;
        }

        void setHasPaws(bool hasPaws) override {
            this->hasPaws = hasPaws;
        }

        bool getHasPaws() override {
            return hasPaws;
        }

        void print() {
            cout << name << " is a monster!!!" << endl;
            cout << name << " has:" << endl;

            for (string ability : abilities) {
                cout << "- " << ability << endl;
            }
        }
};

int main() {
    Monster dragon;

    dragon.name = "Dragon";
    dragon.feets = 4;
    dragon.hasPaws = true;
    dragon.abilities.push_back("Nuclear blast");
    dragon.abilities.push_back("Ice smoke");

    dragon.print();

    return 0;
}

In C++, an interface is an abstract class with pure virtual functions. It is strong. Let's try to remove any method of Properties from the Monster class, you will get an error even though that method is already defined in its parent, the Animal class.

Constructor

By the way, let's create a constructor for the Monster class. So, we can initialize an object in simple and short.

Monster(string name, int feets, bool hasPaws, vector<string> abilities) {
    this->name = name;
    this->feets = feets;
    this->hasPaws = hasPaws;
    this->abilities = abilities;
}
Monster dragon("Dragon", 4, true, {"Nuclear blast", "Ice smoke"});

The constructor should be public. It has the same name as the class. It has no data type, even void.

Access Modifiers

There are only three types of access modifiers in C++.

Let's refactor our examples. The classes already have getters and setters. So, the properties should be private.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
#include <iostream>

using namespace std;

class Properties {
    public:
        virtual void setName(string name) = 0;
        virtual string getName() = 0;
        virtual void setFeets(int feets) = 0;
        virtual int getFeets() = 0;
        virtual void setHasPaws(bool hasPaws) = 0;
        virtual bool getHasPaws() = 0;
};

class Animal: public Properties {
    protected:
        string name;
        int feets;
        bool hasPaws;

    public:
        void setName(string name) {
            this->name = name;
        }

        string getName() {
            return name;
        }

        void setFeet(int feets) {
            this->feets = feets;
        }

        int getFeet() {
            return feets;
        }

        void setHasPaws(bool hasPaws) {
            this->hasPaws = hasPaws;
        }

        bool getHasPaws() {
            return hasPaws;
        }

        void print() {
            cout << name << " has " << feets << " feets." << endl;
            if (hasPaws) {
                cout << name << " has paws." << endl;
            }
        }
};

class Monster: public Animal {
    public:
        vector<string> abilities;

        Monster(string name, int feets, bool hasPaws, vector<string> abilities) {
            this->name = name;
            this->feets = feets;
            this->hasPaws = hasPaws;
            this->abilities = abilities;
        }

        void setName(string name) override {
            this->name = name;
        }

        string getName() override {
            return name;
        }

        void setFeets(int feets) override {
            this->feets = feets;
        }

        int getFeets() override {
            return feets;
        }

        void setHasPaws(bool hasPaws) override {
            this->hasPaws = hasPaws;
        }

        bool getHasPaws() override {
            return hasPaws;
        }

        void print() {
            cout << name << " is a monster!!!" << endl;
            cout << name << " has:" << endl;

            for (string ability : abilities) {
                cout << "- " << ability << endl;
            }
        }
};

int main() {
    Monster dragon("Dragon", 4, true, {"Nuclear blast", "Ice smoke"});

    dragon.print();

    return 0;
}    

Closing

All examples are in https://github.com/aristorinjuang/cpp-oop. I hope this article can help you to understand OOP in C++.

Related Articles

Comments

comments powered by Disqus