Sign in to follow this  
zerotri

Why does GCC output a 'abstract virtual called from' warning.

Recommended Posts

I've been getting this warning with some new code:
warning: abstract virtual 'virtual void WSPhysicsComponent::initialize()' called from constructor


It's not a big deal, I know exactly why I'm getting it. What I don't understand, is why GCC feels the need to inform me of this. GCC won't let me allocate this base class for anything, so it's not like the constructor will be called from a class that still has the abstract form of the function. Maybe I'm just being too picky about it, but it really seems a bit unnecessary for GCC to inform me of. Is there a case where this can be worked around, and the abstract class can be constructed?

Thanks for any info,
-Wynter Woods

[Edited by - zerotri on September 30, 2010 8:29:32 PM]

Share this post


Link to post
Share on other sites
Inside the constructor for a class Foo, a virtual call is resolved using Foo's implementation of the function regardless if any derived class has implemented that virtual function.

Share this post


Link to post
Share on other sites
So if I were to call the constructor in a child class like so:

class ObjectPhysics : public WSPhysicsComponent
{
public:
ObjectPhysics(WSEntity *entity)
: WSPhysicsComponent(entity)
{
}
void initialize()
{
m_pEntity->set<CSPoint<s32_t> >("position",CSPoint<s32_t>(32,32));
};
void update(Time_t deltaTime)
{
};
};



It would call the abstracted base version of initialize rather than the child class' version?
Interesting. Gotta fix the design of that class a bit then. Another odd thing to me is that if I prefix the original line to call initialize with 'this->' it won't give me the warning anymore, but also won't link if I try to build using a child class.

EDIT: the linker error may have been due to me not prefixing the virtual functions in the child class with the word 'virtual'. Can't test now because I've changed the code a bit to fix another problem in the design.

Thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by zerotri
So if I were to call the constructor in a child class like so:
*** Source Snippet Removed ***
It would call the abstracted base version of initialize rather than the child class' version?
Interesting. Gotta fix the design of that class a bit then. Another odd thing to me is that if I prefix the original line to call initialize with 'this->' it won't give me the warning anymore, but also won't link if I try to build using a child class.

EDIT: the linker error may have been due to me not prefixing the virtual functions in the child class with the word 'virtual'. Can't test now because I've changed the code a bit to fix another problem in the design.

Thanks!


The child class need not have virtual in the function prototype. It will be considered virtual if the base class only has it as well. However avoid calling virtual functions in a constructor. Its a bad design.

Secondly as the previous posted pointed out why do you have initialize as a virtual function and aren't just doing things in the constructor.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Did you write this base class? Why does it have an initialize() function instead of just using the constructor?


The current design of the base class is as follows:
class WSComponent : public WSPropertyContainer
{
public:
void _preInit(WSEntity* entity)
{
initialize();
}
virtual void initialize() abstract;
protected:
WSEntity* m_pEntity;
};

The _preInit function is called in the constructor of the WSEntity class, as three component types are passed in to the entity class. The entity class passes it's own pointer into the _preInit of each component, which each save the entity pointer into a member variable. The initialize function is then called on all of the components, allowing them to save any properties necessary into the entity. The reason the constructor cannot be used for storing properties is because in the case of this code:
entity = new WSEntity(new ObjectGraphics,
new PlayerInput,
new ObjectPhysics);

The variable entity needs to be passed into each of the components before they can be initialized, and cannot be passed in this way. If any of you have any suggestions, I'd love to hear them, as I'm always looking for a better alternative design to my code. My goal for this project is code reuse, at least for myself.

Thanks for your criticisms,
-Wynter Woods

Share this post


Link to post
Share on other sites
Quote:
The _preInit function is called in the constructor of the WSEntity class

I would think you need to show the constructor as your description and the code shown do not match with the error you are getting. The physics component would be fully constructed by the time any function is called on it in the Entity constructor.

Please do not try and simplify the code yet show the actual code, also with the abstract keyword you are using it would seem this is not C++ yet C++/CLI is this correct?

Quote:
The reason the constructor cannot be used for storing properties is because in the case of this code:

I suspect (without knowing all the details) what you actually want is a factory function but that is jumping the gun a little.

Share this post


Link to post
Share on other sites
Quote:
Original post by CmpDev
Quote:
The _preInit function is called in the constructor of the WSEntity class

I would think you need to show the constructor as your description and the code shown do not match with the error you are getting. The physics component would be fully constructed by the time any function is called on it in the Entity constructor.

Please do not try and simplify the code yet show the actual code, also with the abstract keyword you are using it would seem this is not C++ yet C++/CLI is this correct?

Quote:
The reason the constructor cannot be used for storing properties is because in the case of this code:

I suspect (without knowing all the details) what you actually want is a factory function but that is jumping the gun a little.


I'm not getting any errors anymore. The design works as is, but I'm curious now about any ideas on how to make the code more reusable. I do plan on using a factory design, but that is to come once I've got a fairly solid design for this part of my code. The 'abstract' in my code is just a #define for '= 0'. It's just plain old C++.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this