Virtual base-class method called instead of derived-class method

Started by
3 comments, last by polyfrag 10 years, 8 months ago

All my other derived-class methods are called correctly but this one isn't for some reason.


class Widget
{
public:
	//...
	
	virtual void draw()	{}
	virtual void draw2()	{}
	virtual void frameupdate()	{ /* g_log<<"widg frameup"<<endl; g_log.flush(); */ }
	//...
};

class EditBox : public Widget
{
public:
	//...
	void draw();
	//...
	void frameupdate();
	//...
};

#define MOUSESC_DEBUG

void EditBox::frameupdate()
{
#ifdef MOUSESC_DEBUG
	g_log<<"editbox frameup"<<endl;
	g_log.flush();
#endif

	//...
}

class View
{
	//...

	void frameupd()
	{
		//g_log<<"view frameup"<<endl;
		//g_log.flush();

		for(auto i=widget.begin(); i!=widget.end(); i++)
			(*i)->frameupdate();
	}

	//...
};

The View calls frameupdate(); on each member widget, none of which are the base class (all are some derived type) and some are EditBox type.

Views output "view frameup" to the log.

The base class method frameupdate(); outputs "widg frameup" to the log.

The EditBox derived class outputs "editbox frameup".

What I can see in the log is "view frameup" and "widg frameup" but no "editbox frameup". The derived frameupdate(); method isn't being called. What the heck?

Advertisement

Are you storing your widgets by value or by pointer? If by value, then you've probably got a slicing issue going on.

I see an 'auto' in there, so you're using C++11, right? . This means you probably have access to the 'override' keyword, which you should use when overriding virtual functions, because then the compiler will explicitly warn you (at compile time) if there's any accidental mis-matches in function signatures, which sometimes accidentally results in what you're encountering.

(I don't know if the function signatures were "cleaned up" or not when you posted)

For example, if:


Base:
virtual void frameupdate() const

Derived:
void frameupdate() //not-const

It won't properly be overridden, because the second frameupdate() is actually a different function signature because of the lack of const.


Another non-related tip is that you could re-write your for() loop like this:


for(Widget *widget : this->widgets)
{
    widget->frameupdate();
}

Are you storing your widgets by value or by pointer? If by value, then you've probably got a slicing issue going on.

He uses (*it)-> to access the member so the widgets should be stored by pointer.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.

Figured it out. Wasn't relaying the frameupdate(); call to child sub-widgets.

This topic is closed to new replies.

Advertisement