Jump to content
  • Advertisement
Sign in to follow this  
signal_

Problem with Virtual Function

This topic is 3559 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I recently have begun to use virtual functions. I am having a problem at run time. Can someone please check my syntax and methods? See below for an explanation of the outcome. Here is my code. I have broken it up into files because that is how it is in my work directory. I think the problem may lie with my syntax. entity.h file:
class Entity
{
    protected:
        int xCo; int yCo;   // coordinates for the entity

    public:

        Entity( eID );

        ~Entity();
        
        virtual void update();                                   
};





Entity.cpp file:
#include "entity.h"



Entity::Entity( eID )
{
    // do stuff
}


Entity::~Entity()
{
}



void Entity::update()  // Update Function -- called once per frame.
{
    std::cout << "***Update" << std::endl;
}






Then I have a derived class that I want to use. derive.h file:
#include "entity.h"


class Derive: public Entity
{
  public:
    Derive( eID );
    ~Derive();

    void update();

};





derive.cpp file:
#include "derive.h"



Derive::Derive( eID ):Entity( eID )
{
    //

}

void Derive::update()
{
    std::cout << "UpdateDerive!!!!!!!!!!!!!!!" << std::endl;
}


Derive::~Derive()
{
}






Basically, I create a vector: std::vector<Entity*> entities; Then I call a function: void EntityList::updateEntity() { for( int i = 0; i < entities.size(); i++ ) // i < entity_ID { entities->update(); } } When I run the program it says MS Windows detected a problem & closes. Compiles and links without problem. I also completely rebuilt the project. When I remove the virtual keyword, i.e. type "void update();" instead of "virtual void update();" in the entity.h file the program runs and exits fine. Of course the added functionality of derived classes isn't there but it runs. What am I doing incorrectly? Please assist.

Share this post


Link to post
Share on other sites
Advertisement
You must make the destructor of the base class 'virtual'. (I assume you do actually have code somewhere that allocates entities with 'new' and puts them into the vector, and which calls 'delete' on those pointers later.) (You must also ensure that each created object is only deallocated once.)

Basically: the destructor is a member function, too. If it's not 'virtual', then it won't do any dynamic dispatch, which means the base destructor gets called on the pointed-at object, even if it's actually an instance of the derived class. And that's bad.

Share this post


Link to post
Share on other sites
As a rule, a class with a virtual function should have a virtual destructor. Here is a link that more correctly explains the rule (section 20.7). Other than that, I don't know what the problem could be. I assume that entities is filled with valid objects, of course.

[edit]

Ah fetch! Ninja'd twice!

Share this post


Link to post
Share on other sites
1) Run the program in your debugger to, among other things, find out exactly where the crash occurs (clicky)
2) Entity must have a virtual destructor. As is, the following code may explode:
Entity* foo = new Derive();
delete foo;



3) Please always copy & paste real source code. (If you really are directly copy and pasting a class named "Derive" from what you're compiling, you may want to start naming your classes better ;-))

If the crash is actually occurring on the update() call, I'm guessing your vector contains uninitialized, deleted, or otherwise invalid pointers. Since update() doesn't access any of the member variables of the class (or functions that do so themselves), the implicit "this" pointer isn't actually being used when update isn't virtual. By making the function virtual, your compiler beings using the implicit "this" pointer to get the virtual table so it can call the correct function for the class you're using.

A way to confirm this would be to make Entity::update print out xCo and yCo instead of just "***Update". This would cause the code to crash even if the function isn't virtual if my guess is right.

Edit: Ninja'd thrice <_<

Share this post


Link to post
Share on other sites
Wow! Thanks for all the quick replies. I was asked about how I am adding entities to my vector, so I will include that now:


void EntityList::addEntity(int x, int y)
{
Entity* temp_entity = new Entity( entity_ID );

// now increment ID entity!
entity_ID++;

temp_entity->SetX( x );
temp_entity->SetY( y );


entities.push_back( temp_entity ); // create the entity!


delete temp_entity;
}





I am afraid that I need to read through all the responses thus far to offer a better reply. But until then thanks for all the responses!

Share this post


Link to post
Share on other sites
SiCrane,

I am obviously confused here... By deleting it I am just ruining what I just did, right?

What I want is a container for the entities and all these different entities to use their respective update functions.

So, do I need to store all my entities in a vector and store my entity pointers in another? Sorry I am confused.

Share this post


Link to post
Share on other sites
Quote:
Original post by signal_
SiCrane,

I am obviously confused here... By deleting it I am just ruining what I just did, right?

What I want is a container for the entities and all these different entities to use their respective update functions.

So, do I need to store all my entities in a vector and store my entity pointers in another? Sorry I am confused.


No, the problem is you create the object, store it, and then delete it. That means that the vector now contains a bunch of deleted objects. Trying to use them crashes your program. You should do something more like

void EntityList::addEntity(int x, int y)
{
Entity* temp_entity = new Entity( entity_ID );

// now increment ID entity!
entity_ID++;

temp_entity->SetX( x );
temp_entity->SetY( y );


entities.push_back( temp_entity ); // create the entity!
}




And in the destructor of the class (or somewhere that it will be called so your memory doesn't leak), iterate through the vector and delete the objects, like this:

for (int i = 0; i < entities.size(); i++)
{
delete entities;
}

entities.clear();


Share this post


Link to post
Share on other sites
Mike, by removing that delete line and making the changes you outlined everything works now the way I intended.

I am weak with pointers and usually avoid using them, which explains my confusion with new and delete. Also there are some aspects of OOP that I am very shaky with. I come from a C background and was not a comp sci student at uni (this is obvious to all of you, but I am being complete...lol).

I have a lot to learn and I truly appreciate everyone who took the time to respond to my post. Thank you so much!

Unfortunately, I must run out for a quick errand so I will write more when I return.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!