Inheritance, calling a children method from parent

Hello, I am new to the forums as recently started learning C++, and I am trying to wrap my head around C++ from a C# developer perspective.

I am making a game for the first time. Here is a overall information:
- There is a ScreenManager class which has a list of GameScreen, and calls GameScreen's methods.
- GameScreen is the parent class of SplashScreen and has virtual methods.
- SplashScreen overrides the methods of its parent class.
- In the main, I create a ScreenManager, which should call the methods of a SplashScreen added into the list of GameScreens.

The problem is that the ScreenManager object in the main function only calls 1 method correctly (the first one) but the other two are ignored.

I want to know why it doesn't call the other two methods and if there is a better way to do this.

Thank you in advance.


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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
///////////////////////////
// main.cpp
///////////////////////////
#include <iostream>
#include "ScreenManager.h"
#include "SplashScreen.h"

ScreenManager ScreenManager;

bool init()
{
    bool success = true;
    SplashScreen splash = SplashScreen();
    ScreenManager.AddScreen(&splash);
    if(!ScreenManager.LoadMedia())
    {
        success = false;
    }
    return success;
}

int main()
{    
    if(!init())
    {
        std::cout << "Failed to initialize!\n";
    }
    else
    {
        ScreenManager.Update();
	ScreenManager.Draw();
    }

    return 0;
}
///////////////////////////
// ScreenManager.h
///////////////////////////
#include <list>
#include "GameScreen.h"

class ScreenManager
{
    public:
        ScreenManager();
        virtual ~ScreenManager();
        void AddScreen(GameScreen* gameScreen);
        bool LoadMedia();
        void Draw();
        void Update();

    private:
        std::list<GameScreen*> screenList;
};
///////////////////////////
// ScreenManager.cpp
///////////////////////////
#include "ScreenManager.h"

ScreenManager::ScreenManager(){}

ScreenManager::~ScreenManager(){}

void ScreenManager::AddScreen(GameScreen* gameScreen)
{
    screenList.push_back(gameScreen);
}

bool ScreenManager::LoadMedia()
{
    return screenList.back()->LoadMedia();
}

void ScreenManager::Draw()
{
    if (!screenList.empty())
    {
        screenList.back()->Draw();
    }
}

void ScreenManager::Update()
{
    if (!screenList.empty())
    {
        screenList.back()->Update();
    }
}
///////////////////////////
// GameScreen.h
///////////////////////////
class GameScreen
{
    public:
        GameScreen();
        virtual ~GameScreen();
        virtual bool LoadMedia();
        virtual void Draw();
        virtual void Update();
};
///////////////////////////
// GameScreen.cpp
///////////////////////////
#include "GameScreen.h"

GameScreen::GameScreen(){}

GameScreen::~GameScreen(){}

bool GameScreen::LoadMedia()
{
    return true;
}

void GameScreen::Draw(){}

void GameScreen::Update(){}
///////////////////////////
// SplashScreen.h
///////////////////////////
#include "GameScreen.h"

class SplashScreen : public GameScreen
{
    public:
        SplashScreen();
        virtual ~SplashScreen();
        bool LoadMedia() override;
        void Draw() override;
        void Update() override;
};
///////////////////////////
// SplashScreen.cpp
///////////////////////////
#include "SplashScreen.h"
#include <iostream>

SplashScreen::SplashScreen(){}

SplashScreen::~SplashScreen(){}

bool SplashScreen::LoadMedia()
{
    std::cout << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!\n";
    return true;
}

void SplashScreen::Draw()
{
    std::cout << "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB!\n";
}

void SplashScreen::Update()
{
    std::cout << "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC!\n";
}


Output:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!


...Program finished with exit code 0
Last edited on
splash is a local variable inside the init() function so it will go out of scope (and get destroyed) as soon as the function ends which leaves a dangling pointer in the screen list.
Last edited on
Forget what you know about c# memory management (ie .net) when coding for C++. They are different. In C++ stack-based (local) variables are only valid in the scope in which they are defined. Once out of scope, they are no longer valid. Hence any memory reference to these variables is also invalid once they are out of scope. If you wish to use a memory reference to a variable then you need to use dynamic memory (with new/delete or a managed pointer [nothing to do with c# managed variables!] ). Then some code has to be responsible for freeing the allocated memory if new/delete used as this isn't done automatically as it is c#.

https://www.learncpp.com/cpp-tutorial/scope-duration-and-linkage-summary/
https://www.learncpp.com/cpp-tutorial/intro-to-smart-pointers-move-semantics/
https://www.learncpp.com/cpp-tutorial/introduction-to-pointers/
https://www.learncpp.com/cpp-tutorial/dynamic-memory-allocation-with-new-and-delete/
Thank you! That makes sense. Is there an alternative to this? I want to create the object and keeping it instead of getting destroyed.
I think our posts crossed...
Thank you! That makes sense. Is there an alternative to this? I want to create the object and keeping it instead of getting destroyed.

Allocate it on the heap, via new operator.

But then you will have to explicitly delete the object, at some point of your program, in order to avoid a memory leak. C++ does not have a garbage collector that "automatically" removes unneeded objects for you ! ;-)
Last edited on
You could create the object with new. That way it will not get destroyed until you use delete.

You might also want to look into "smart pointers", such as std::unique_ptr, which are often helpful when dealing with such "dynamically allocated objects".
Last edited on
Thank you all for your replies, now I understand I more about it! I am going to mark this as solved as there is much information I need to look at, but now I am confident in how to do it.

Thanks again.
depending on what you are doing, static (keyword) class variables always exist but they are shared across all the class instances. You can even access them without a class instance. This isn't normally the way to deal with what you are doing, but if you only have one instance of the class it can save the dynamic memory aggravation. Anyway its another tool that you will want at some point.
Topic archived. No new replies allowed.