aboutsummaryrefslogtreecommitdiffstats
path: root/src/lesson22_oop_virtl01.cpp
blob: a07d866a435afb3b6ad4dcea46ea8b0a20047bb7 (plain)
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
106
107
108
109
110
111
//============================================================================
// Author      : Sven Göthel
// Copyright   : 2024 Göthel Software e.K.
// License     : MIT
// Description : C++ Lesson 2.2 OOP (inheritance w/ virtual functions)
//============================================================================

#include <limits>
#include <string>
#include <memory>
#include <cassert>
#include <iostream>

class creature_t {
    private:
        int m_init_lifetime_left;
        int m_lifetime_left;

    protected:
        /** Custom constructor (ctor) */
        creature_t(int lifetime_left) noexcept
        : m_init_lifetime_left(lifetime_left),
          m_lifetime_left(lifetime_left) {}

        /** Copy ctor */
        creature_t(const creature_t& o) noexcept = default;

    public:
        /** Virtual destructor (dtor) */
        virtual ~creature_t() noexcept = default;

        int total_lifetime() const noexcept { return m_init_lifetime_left; }
        int lifetime_left() const noexcept { return m_lifetime_left; }
        int age() const noexcept { return total_lifetime() - lifetime_left(); }
        bool alive() const noexcept { return lifetime_left() > 0; }
        std::string lifesign() const noexcept { return alive() ? "☀" : "✝"; }

        /** Subtract given years of life and return whether there is lifetime left */
        bool tick(int years) noexcept {
            if( m_lifetime_left > years ) {
                m_lifetime_left -= years;
                return true;
            } else {
                m_lifetime_left = 0;
                return false;
            }
        }

        /** Fully virtual to_string() method to be implemented in children classes */
        virtual std::string to_string() const noexcept = 0;

    protected:
        std::string to_substring() const noexcept {
            return "age "+std::to_string(age())+"/"+std::to_string(total_lifetime());
        }
};

std::ostream& operator<<(std::ostream& out, const creature_t& v) {
    return out << v.to_string();
}

class plant_t : public creature_t {
    public:
        /** Custom constructor (ctor) */
        plant_t(int lifetime_left) noexcept
        : creature_t(lifetime_left) {}

        /** Copy ctor */
        plant_t(const plant_t& o) noexcept = default;

        /** Virtual to_string() override  */
        std::string to_string() const noexcept override { return "plant"+lifesign()+"["+creature_t::to_substring()+"]"; }
};

class animal_t : public creature_t {
    public:
        /** Custom constructor (ctor) */
        animal_t(int lifetime_left) noexcept
        : creature_t(lifetime_left) {}

        /** Copy ctor */
        animal_t(const creature_t& o) noexcept
        : creature_t(o) { }

        /** Virtual to_string() override  */
        std::string to_string() const noexcept override { return "animal"+lifesign()+"["+creature_t::to_substring()+"]"; }
};

int main(int, char*[]) {
    plant_t p1(3);
    animal_t a1(80);

    std::cout << "00.p1 = " << p1 << std::endl;
    std::cout << "00.a1 = " << a1 << std::endl;

    creature_t& c1p1 = p1, &c2a1 = a1;
    std::cout << "00.c1p1 = " << c1p1 << std::endl;
    std::cout << "00.c2a1 = " << c2a1 << std::endl;

    p1.tick(1);
    a1.tick(1);
    std::cout << "01.p1 = " << p1 << std::endl;
    std::cout << "01.a1 = " << a1 << std::endl;

    p1.tick(2);
    a1.tick(79);
    std::cout << "03.p1 = " << p1 << std::endl;
    std::cout << "79.a1 = " << a1 << std::endl;

    return 0;
}