Calling inherited classes function from base class

Hello, I'm trying to call a function from a class that has inherited from a base class. I've seen this been done, but unfortunately I get a crash when running the program.

Hello, I'm trying to call a function from a class that has inherited from a base class. I've seen this been done, but unfortunately I get a crash when running the program.

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
class Enemy {

public:
	Enemy()
	{
		instances.push_back(this);
	}
	virtual bool AttemptAttack()
	{
		std::cout << "An enemy attacked\n";
		return true;
	}
	virtual bool Render()
	{
		for (std::vector<Enemy*>::iterator i = instances.begin(); i != instances.end(); ++i)
		{
			(*i)->Render();
		}
		return true;
	}
private:
	std::vector<Enemy*>instances;
};

class BogeyMan : public Enemy{
public:
	BogeyMan()
	{}

	bool AttemptAttack()
	{
		std::cout << "The bogey man attacked!\n";
		return true;
	}

	bool Render()
	{
		std::cout << "Frame rendered.\n";
		return true;
	}
};

int main()
{
	Enemy *mrBogey = new BogeyMan();
	mrBogey->AttemptAttack();
	Enemy *enemies = new Enemy();
	while (1)
	{
		enemies->Render();
	}

	delete mrBogey;
	mrBogey = nullptr;
	delete enemies;
	enemies = nullptr;
	std::cin.get();
	return 0;
}
Last edited on
The error is caused by Enemy recursively calling its own Render() function.

From the look of the classes, you are trying to get enemies to call the render of mrBogey through the instances variable. This does not work because both objects create their own instances variable.
Thanks for the reply. I've managed to fix the initial crash by declaring the instances vector as a global variable. However, the program now crashes with a stack overflow.

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
#include <iostream>
#include <vector>

class Enemy;

std::vector<Enemy*>instances;

class Enemy {

public:
	Enemy()
	{
		instances.push_back(this);
	}
	virtual bool AttemptAttack()
	{
		std::cout << "An enemy attacked\n";
		return true;
	}
	virtual bool Render()
	{
		for (std::vector<Enemy*>::iterator i = instances.begin(); i != instances.end(); ++i)
		{
			(*i)->Render();
		}

		return true;
	}

};


class BogeyMan : public Enemy{
public:
	BogeyMan()
	{}

	bool AttemptAttack()
	{
		std::cout << "The bogey man attacked!\n";
		return true;
	}

	bool Render()
	{
		std::cout << "Frame rendered.\n";
		return true;
	}
};

class Test1 : public Enemy {

public:
	Test1()
	{
	}

	bool Render()
	{
		std::cout << "Test1 bla\n";
		return true;
	}
};

int main()
{
	Enemy *mrBogey = new BogeyMan();
	mrBogey->AttemptAttack();
	Enemy *test = new Test1();
	Enemy *enemies = new Enemy();
	while (1)
	{
		enemies->Render();
	}

	delete mrBogey;
	mrBogey = nullptr;
	delete enemies;
	enemies = nullptr;
	std::cin.get();
	return 0;
}


EDIT: Forgot you've already stated the error, and I see that now. How do I fix this recursion?

EDIT2: Fixed.
Last edited on
It's still exactly the same problem - Enemy::Render() is calling itself recursively, an infinite number of times.

Why is Enemy::Render() calling the Render() method on multiple Enemy objects (including itself)?

It looks to me as though you might be confused about what you want the Enemy class to represent. Is it a single enemy, or is it a collection of enemies?

I've fixed it with the following code:

1
2
3
4
5
6
7
8
9
10
virtual bool Render()
	{
		for (std::vector<Enemy*>::iterator i = instances.begin(); i != instances.end(); ++i)
		{
			if((*i) != this)
				(*i)->Render();
		}

		return true;
	}


It would be a collection of Enemies. This is actually some playing around I'm doing, most likely going to use this in a rendering engine of some sort -- Have a base rendering class which will include all the required things such as render, pre-render etc which things like a lighting class can inherit from and automatically be added to the game loop through this method.
I think your modified code will still have the same problem. When more than one enemy is the list, Enemy 1 will call Render() on Enemy 2, which will call Render() on Enemy 1, which will call Render() on Enemy 2, etc.

You need to think more clearly about the design. Separate out the idea of an "enemy" from the idea of "a collection of enemies". Have different classes to represent those different concepts. Then the collection class can iterate over the individual enemies, calling Render() on each one in turn.
I've just checked and the code doesn't seem to have the same problem.

Test code:

1
2
3
4
5
6
int i = 1;
	while (i < 6)
	{
		enemies->Render();
		i++;
	}


Five rendering calls should take place.

https://i.imgur.com/i6oLP8v.png

The code works.

As for the design of the class, it isn't finished. This code was more of a proof of concept, to prove that I can get this code to run fine so I can implement it for its actual use later.

The final class would look somewhat like this: (This is for a rendering engine)

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
class Renderer;

std::vector<Renderer*>instances;

class Renderer {

public:
	Renderer()
	{
		instances.push_back(this);
	}
	virtual bool VPreRender()
	{
		std::cout << "An enemy attacked\n";
		return true;
	}
	virtual bool VRender()
	{
		for (std::vector<Renderer*>::iterator i = instances.begin(); i != instances.end(); ++i)
		{
			if((*i) != this)
				(*i)->VRender();
		}
		return true;
	}
};

class Lighting : public Renderer {
public:
	Lighting()
	{}

	virtual bool Render()
	{
		std::cout << "Rendering light to the screen.\n";
		// Other graphical functions
		return true;
	}
};

class Object : public Renderer {
public:
	Object()
	{}

	virtual bool VPreRender()
	{
		std::cout << "This is called before the object is rendered to the screen\n";
		return true;
	}

	virtual bool Render()
	{
		std::cout << "An object has been rendered\n";

		// Other graphical functions
		return true;
	}
};
I've just checked and the code doesn't seem to have the same problem.

How many items did you have in your instances vector?
3. 2 inherited classes and the base class. I'm not really sure how to make it so it doesn't add the base class to the vector, the if((*i) != this) prevents it from causing a problem but if you know a better way of getting round this please let me know.
You could split it up so that you have things that can be rendered. The base class could be called Renderable, or RenderableObject or sometihng like that.

And then you could have a Renderer class that handles the Renderable objects and makes sure they are being rendered correctly.

Something like this:
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
class Renderer {
public:
	bool Render()
	{
		for (std::vector<Renderer*>::iterator i = renderables.begin(); i != renderables.end(); ++i)
		{
			(*i)->Render();
		}
		return true;
	}
	void add(Renderable* renderable)
	{
		renderables.push_back(renderable);
	}

private:
	std::vector<Renderable*> renderables;
};

class Renderable {
public:
	virtual bool Render() = 0;

};

class Lighting : public Renderable {
public:
	virtual bool Render()
	{
		std::cout << "Rendering light to the screen.\n";
		// Other graphical functions
		return true;
	}
};

class Object : public Renderable {
public:
	virtual bool Render()
	{
		std::cout << "An object has been rendered\n";

		// Other graphical functions
		return true;
	}
};
Last edited on
Topic archived. No new replies allowed.