0

I am just starting to really understand Polymorphism, but still this is a new topic for me. So here is my Problem: I have to classes, enemy and Bankrobber. However Bankrobber inherits from enemy. I tried to make an array of 10 Bankrobbers. A global function should then use all members of the array to do something, well I guess this is a worthless description, so here is the code:

void UpdateEnemies(Enemy * p_Enemy, int counter) { 
    for(unsigned int i = 0;i < counter;i++) { 
        p_Enemy[i].Update(); 
    } 
}

int main(void) { 
    BankRobber EnemyArray[10]; 
    Enemy * p_Enemy = new BankRobber(13,1); 
    UpdateEnemies(EnemyArray,10); 
    system("PAUSE"); 
};   

I apologize for any language mistakes. I am not a native speaker

My actual Problem: This code is just for practicing, so the purpose is just to see 10 times Update on the console, for each member of the Array. So the function UpdateEnemys should call all the enemy.update functions. The method with the type casting is not exactly what I want, cause it is not dynamicly anymore, as there will be more enemy later on. Not only Bankrobbers.

6
  • I am very sorry for this comment, but I can't get the highlighting to work. Commented Sep 4, 2013 at 12:35
  • void UpdateEnemies(Enemy * p_Enemy, int counter) { for(unsigned int i = 0;i < counter;i++) { p_Enemy[i].Update(); } } int main(void) { BankRobber EnemyArray[10]; Enemy * p_Enemy = new BankRobber(13,1); UpdateEnemies(EnemyArray,10); system("PAUSE"); }; Commented Sep 4, 2013 at 12:35
  • I'm not sure what your question is, but you should read parashift.com/c++-faq/array-derived-vs-base.html. Commented Sep 4, 2013 at 12:38
  • it is just for practicing purpose, I understand, that there are better methods on realizing, what I want to do. It's just, the code doesn't wok, because it trys to refer something, that doesn't exist Commented Sep 4, 2013 at 12:40
  • 1
    You forgot to explain what exactly your problem is. What is that code supposed to do and what happens instead? Commented Sep 4, 2013 at 12:41

3 Answers 3

2

Polymorphism only works on single objects, accessed by a reference or pointer to a base class. It does not work on an array of objects: to access array elements, the element size must be known, and that's not the case if you have a pointer to a base class.

You would need an extra level of indirection: an array of pointers to single objects, along the lines of

void UpdateEnemies(Enemy ** p_Enemy, int counter) { 
    for(unsigned int i = 0;i < counter;i++) { 
        p_Enemy[i]->Update(); 
    } 
}

int main() {
    // An array of Enemy base-class pointers
    Enemy * EnemyArray[10]; 

    // Populate with pointers to concrete Enemy types
    for (unsigned i = 0; i < 9; ++i) {
         EnemyArray[i] = new BankRobber;
    }

    // Of course, the array can contain pointers to different Enemy types
    EnemyArray[9] = new Dragon;

    // The function can act polymorphically on these
    UpdateEnemies(EnemyArray,10);

    // Don't forget to delete them. Enemy must have a virtual destructor.
    for (unsigned i = 0; i < 10; ++i) {
         delete EnemyArray[i];
    }
}

You should also consider using RAII types, such as containers and smart pointers, to manage these dynamic resources; but that's beyond the scope of this question.

Sign up to request clarification or add additional context in comments.

Comments

1

Declaring an array of BankRobber like this

BankRobber EnemyArray[10];

But than acessing them through the base class pointer like this

Enemy * p_Enemy;    
p_Enemy[i].Update();

Wouldn't work. That's because indexing an array p_Enemy[i] will be done by using the offcet sizeof(Enemy)
But sizeof(BankRobber) is probably bigger than from sizeof(Enemy), so p_Enemy[i] will end up in the wrong place

You should use a vector of pointers instead, like

std::vector<Enemy*>

That way you can also use polymorphism if you add pointers to different objects into the vector. And you don't need to pass the ugly int counter around

Comments

0

Indeed you didn't say exactly what is the problem.

Did you try casting inside your code? Something like:

void UpdateEnemies(Enemy * p_Enemy, int counter) { 
    BankRobber *pRobber = (BankRobber*)p_Enemy;
    for(unsigned int i = 0;i < counter;i++) { 
        pRobber[i].Update(); 
    } 
}

6 Comments

@Ben Hymers: Can you explain why it will not work? (apart from OP's comment which I understand, when he said that he may have other enemies other than BankRobber - and in that case, I understand). I couldn't deduce why it won't work from other answers..
Well, it'll work if UpdateEnemies knows for sure that the passed in p_Enemy points to an array of BankRobbers, but that's not safe in general :) You could similarly pass in a void* or intptr_t and cast to BankRobber; it's just as nasty.
@Ben Hymers: Well, I see, but at least it works. I just suggested it as a possible solution ...
It's not a solution though; the OP said he wants it to work with other subclasses of Enemy. Your code looks to callers like it works on pointers to the base Enemy but in fact breaks unless they're actually BankRobbers. I'm not trying to nitpick or be nasty, it's just wrong, sorry!
@Ben Hymers: The OP said he wanted it to work with other subclasses of Enemy after I posted this solution ...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.