0

I'm trying to workout a problem in C++ regarding inheritance and wondering how to go about doing it correctly.

I have 3 classes set up: - Enemy (which has member data: int Damage, int Health and int Level) - Wolf - Bear

The way my inheritance is set up is: Wolf is-a Enemy and Bear is-a Enemy. In other words, both Wolf and Bear inherit from Enemy.

I want to set up my program so that when I create a new Enemy like so:

Enemy anEnemy; 

Then in Enemy::Enemy() constructor it will randomly decide whether that enemy is a Wolf or a Bear.

How would one approach this problem? I know I'd have to generate a random number in the Enemy::Enemy() constructor and based on the result of the random number it would turn the enemy into either a bear or wolf. But I just can't wrap my head around how to "turn it" (the enemy) into a wolf or a bear.

Any help would be really appreciate. Thanks!

Shawn
  • 33
  • 4
  • _"But I just can't wrap my head around how to "turn it" (the enemy) into a wolf or a bear."_ You don't _"turn"_ these instances into a _wolf or a bear_, but have these (wolf/bear) instantiated in 1st place. Check what `std::unique_ptr` or `std::shared_ptr` can do for you. – πάντα ῥεῖ Mar 16 '15 at 23:49
  • Lookup the "Factory" design pattern. – Les Mar 16 '15 at 23:56

2 Answers2

2

To decide the type randomly at run time, then for type safety you practically have to use dynamic allocation, e.g.

Enemy* p_enemy = random_enemy();

// Use p_enemy here, e.g. p_enemy->make_noises(), then:
delete p_enemy;

where random_enemy is a function like

auto random_enemy()
    -> Enemy*
{
    return (my_random_number() > 0.5? new Wolf : new Bear);
}

As you'll discover, however, manual delete is difficult to get right in many/most situations. Therefore it's common to automate that, by using smart pointers such as std::unique_ptr and std::shared_ptr. Then the usage code might look like:

unique_ptr<Enemy> p_enemy = random_enemy();

// Use p_enemy here, e.g. p_enemy->make_noises(), then it auto-deletes.

And the function like

auto random_enemy()
    -> unique_ptr<Enemy>
{
    return unique_ptr<Enemy>(
        my_random_number() > 0.5? new Wolf : new Bear
        );
}
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

You have 2 problems right now :

First, polymorphism (look it up) is based on references or pointers, not values. Therefore, when you create your Ennemy (who might be a Bear or Wolf "at random") you cannot hold a variable of value type to it, because the type won't always be the same.

Ennemy my_ennemy = (Bear or Wolf); // This is impossible.

Essentially Bear and Wolf are not the same type, and not even of the same size, so they cannot fit inside an allocated Ennemy-sized amount of memory.

You need something along these lines :

Ennemy *my_ennemy = new Bear(); // OR
Bear someExistingBear;
Ennemy *my_ennemy = &someExistingBear; // Or even
std::unique_ptr<Ennemy> my_ennemy(new Bear());

Conversely, you have to decide whether to build a Bear or a Wolf outside of the Ennemy constructor.

You could use a free function like so :

Ennemy *make_ennemy() {
     // Some random way to choose. Probably with a static seed.
    if (isbear)
        return new Bear();
    else
        return new Wolf();
}
Félix Cantournet
  • 1,941
  • 13
  • 17