Here is my issue:
In my GUI, there are several types of listeners. They are stored in std::vector<WhateverListener*>
In my GUI, I have a method called removeListeners and it looks like this:
void Widget::removeListeners( Widget* widget )
{
removeFocusListener((FocusListener*)widget);
removeMouseListener((MouseListener*)widget);
removeKeyboardListener((KeyboardListener*)widget);
removeWidgetListener((WidgetListener*)widget);
}
Basically, I do not think it should matter how I cast it; they are just pointers. I think std::remove simply compares pointers, therefore if I provide a widget* then it shouldn't affect anything (I think).
How the remove functions look is something like this:
void Widget::removeWidgetListener(
WidgetListener *listener )
{
widgetListeners.erase(
std::remove(widgetListeners.begin(),
widgetListeners.end(), listener),
widgetListeners.end());
}
So, in the Widget destructor, I iterate through the widget's children and call removeListeners():
Widget::~Widget(void)
{
for(std::vector<Widget*>::iterator it = getChildBegin();
it != getChildEnd(); ++it)
{
(*it)->removeListeners(this);
(*it)->parentWidget = NULL;
(*it)->_container = NULL;
}
}
It does not work. After calling delete on a Widget which was listening to its children, the children still had listeners.
However, if I call the remove methods directly, and the widget inherits from the listener, it works:
Widget::~Widget(void)
{
for(std::vector<Widget*>::iterator it = getChildBegin();
it != getChildEnd(); ++it)
{
(*it)->removeWidgetListener(this);
(*it)->parentWidget = NULL;
(*it)->_container = NULL;
}
}
So why does one work and not the other? The only difference I spot is that in the first one I'm casting a Widget to that type. But I thought it would just compare pointers and if they were == it would remove it?
I'm afraid you might be getting stung by object identity and virtual base classes in C++
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html
Basically, converting pointers to polymorphics bases, is not guaranteed to result in identical pointer values (when cast to (void*) e.g.).
It should work as long as you store the exact same pointer type as what you cast it to during removal, but I can't be sure without looking at more of your code/widget class hierarchy.
The root of your issue seems to be an incorrect design. The need to cast as you are doing implies that the function is in the wrong place. It's not clear from your post what the relationship between Widgets and the different types of Listener classes are.
You need to rethink where you are calling the removeListeners function from and instead of putting it in the base class destructor, you should put it in the destructor of the class that actually knows which type of listener it is (and only call the correct one).
It's hard to be more specific without getting some more detail on the relationships between your classes. In general, if you have to cast, you should ask yourself if there is a better way to accomplish what it is that's forcing you to cast.
Related
I am relatively new to the OO side of C++, so please forgive this question, which I imagine is relatively straight-forward;
I have some code, loosely like this
SuperClass* super;
if (useSub1())
{
SubClass1 sub1 (s);
super = &sub1;
}
else if (useSub2())
{
SubClass2 sub2 (s);
super = &sub2;
}
super.someMethod();
It should be noted, that the point here is that the Construction of 'sub' is dependent upon the result of the call to someFunction().
Furthermore, there will be multiple if (...) { } constructs like above, each creating a different Object based on a different SubClass of SuperClass, based on some condition.
In summary then SuperClass has a number of Sub-classes, and I want to create the appropriate object type based on an if condition, then use the 'super' object to manipulate them.
Here is my question, I think by doing what I have sub1 (or sub2 for that matter) will go out of scope, so does this leave me with a pointer to nothing?
I hope it is reasonably clear what I am trying to do, I am just not sure how to code it correctly. Any help or advice is gratefully received.
Thanks in anticipation
Read about creational patterns, according to the information in your question: factory or factory method might suit your needs.
That design patterns allows to create objects dynamically in the heap, and you can operate with created object using pointer to a base class.
To prevent memory leaks and properly handle resources I suggest you to use smart pointers:
std::unique_ptr<Type> or boost::shared_ptr<Type>
if you are going to use std::auto_ptr don't use it with containers
As #Ben indicates: use new
SuperClass* super;
if (useSub1()) {
super = new SubClass1(s);
}
else if (useSub2()) {
super =new SubClass2(s)
}
super->someMethod();
Yes, sub1 and sub2 object dtors will be invoked as they go out of scope, and the 'super' pointer will be left pointing to an object in stack of indeterminate state. In some cases, it may still be in valid memory regions, hence not resulting in a segment violation, leading to a subtle bug.
It also looks like you need something like an 'Abstract Factory' design pattern:
http://en.wikipedia.org/wiki/Abstract_factory_pattern
You can use a factory method:
std::unique_ptr<SuperClass> create(const std::string& name)
{
if (name == "Sub1")
return std::unique_ptr<SubClass1>{new SubClass1};
if (name == "Sub2")
return std::unique_ptr<SubClass2>{new SubClass2};
throw std::runtime_error;
}
Here I've used an std::string to choose the type of the object to create, but it could be an enum instead.
Note that std::unique_ptr manages the lifetime of the object by itself, so there is no need to delete anything.
void foo()
{
auto object = create("SubClass1");
object->bar();
} <-- object is deleted automatically
I have two classes. The superclass is a "Component" class, and the subclass is a "Transform" class.
The framework I'm using has a function that returns a list of components of a certain type. However, the list will return them as Component, since the type isn't restricted to a specific subclass (however it's the way I'm using it).
So, in the following scenario, I know that all the returned components will be of the Transform subclass. What I'm doing is I'm iterating over the list and then casting each component to Transform. Here is my code:
std::list<Cistron::Component*,std::allocator<Cistron::Component*>> playerTransforms = objectManager->getComponents(player,"Transform");
std::list<Cistron::Component*>::iterator playerComponentIterator = playerTransforms.begin();
for (playerComponentIterator; playerComponentIterator != playerTransforms.end(); playerComponentIterator++)
{
Transform *tmpTransform = static_cast<Transform*> (*playerComponentIterator);
std::cout << tmpTransform->x ;
std::cout << tmpTransform->y ;
}
How efficient is this? I'm quite new to C++, so I have no idea if there's a better way of doing this.
This isn't a good design, your compiler should generate a warning in this case. Normally, you should upcast your pointer using dynamic_cast. This cast has some runtime cost - aproximately the same as virtual method call but it will generate exception if you try to cast incompatible pointers.
Try to redesign your app to eliminate this code. You should only call virtual methods of the Component class, you shouldn't cast pointer to Component to pointer to Transform. This thing indicate bad design.
One possible desigion is to make getComponents a template method to eliminate cast:
template<class T>
list<T*> getComponents(Player* player, std::string name) {
...
}
or maybe just this:
list<Transform*> getTransfromComponents(Player* player) {...}
In a case when you can't refactor this code, you can always transform your list:
list<Component*> rlist = ...
list<Transform*> llist;
// Upcast all
transform(rlist.begin(),
rlist.end(),
back_inserter(llist),
[](Component* r) {
return dynamic_cast<Transform*>(r);
});
// Remove all null values
llist.remove(nullptr);
The std::list is usually implemented as double-linked list, which means that elements are scattered through the memory, which means that iterating through it is slow. Check: Why is it so slow iterating over a big std::list?
But what I would worry more about is the use of reflection:
objectManager->getComponents(player,"Transform");
that might actually be the real bottleneck of this piece of code.
Suppose I have this setup:
struct XView;
struct X
{
...
XView view;
};
Type XView is only used for this one field; it is internal too, so instantiating it from outside, i.e. using it for anything else is prohibited.
So, assuming any object of XView type is an X::view field, is it possible to find address of X from address of XView, staying fully within behavior defined by C++ standard and without type-punning? I.e. is it possible to do something like this:
void XView::some_function ()
{
X& this_x = some_computations_involving (this);
}
I can of course store a pointer, so this would become as trivial as x = *this->parent_x, but would like to do without one if possible.
EDIT: Note that I need an answer without type-punning involved, otherwise I'd rather use that "just store a pointer" solution.
First approach is to make XView the first member of X, then you can do this:
void XView::some_function ()
{
X & this_x = reinterpret_cast<X&>(*this);
}
Second approach is to use offset when XView is not the first member of the X.
Techinically speaking both of these approaches are same if there is no virtuality involved, only that the first approach is a special case (i.e when offset = 0) of the second approach which is the general case.
As for the edit, I think, without casting it is not possible. You have to store the pointer in XView, Or maintaining a map (or some other data structures) of pointers.
The most important thing is whether you really need accessing the parent object from child object and not vice-versa.
I would suggest you using some kind of bi-directional linked list or something like this.
Could your code be refactored to be more object-oriented? (and possibly using the inheritance (and calling the parent by using the super::some_function...)
In the following, how can I make it such that the program uses the draw method from MainMenuScreen instead of the one from GameScreen?
class GameScreen {
public:
virtual void GameScreen::draw() {
cout << "Drawing the wrong one..." << endl;
}
};
class MainMenuScreen : public GameScreen {
public:
void MainMenuScreen::draw() {
cout << "Drawing the right one..." << endl;
}
};
class ScreenManager {
public:
list<GameScreen> screens;
// assume a MainMenuScreen gets added to the list
void ScreenManager::draw()
{
for ( list<GameScreen>::iterator screen = screens.begin();
screen != screens.end(); screen++ )
{
screen->draw(); /* here it uses the draw method from GameScreen,
but I want it to use the draw method from
MainMenuScreen */
}
}
};
PS: I do not want to make GameScreen::draw purely virtual, so please suggest something else.
how can I make it such that the program uses the draw method from
MainMenuScreen instead of the one from GameScreen?
You can't, unless you call it on a pointer or reference whose actual type is MainMenuScreen.
list<GameScreen> screens;
declares a list of objects, not pointers or references. If you add MainMenuScreen objects to it, they will lose type information because of object slicing and polymorphism will not work. You need:
list<GameScreen*> screens;
or, better yet:
list<shared_ptr<GameScreen> > screens;
You don't want to make draw pure virtual, but you do want to make it (or keep it) virtual. To go with that, you want to make screens a list of pointers (or possibly smart pointers of some sort) to GameScreens rather than a list of GameScreen objects.
As it is right now, when you (attempt to) insert your MainMenuScreen object into the list, it's being "sliced" to actually become a GameScreen object -- therefore, when you walk your list, you're walking a list of objects whose actual types are all GameScreen; hoping to get MainMenuScreen behavior from any of them at that point is futile.
With a list of pointers, a MainMenuScreen will remain exactly that, so when you invoke your virtual function, you'll get the behavior of the actual type.
You've fallen victim to object slicing. The objects in your list are only copies of the objects you inserted into it, and as each copy was made it got demoted to the contained type.
The way around this is to insert pointers (preferably smart pointers such as shared_ptr) into the list.
First off: I searched half the web to find an answer with this as a solution that came closest. It is, however, too heavyweight for me though so I am looking a little less complex.
Well then, some context: I am building a system which should be able to process incoming messages from a queue and then store the outcome of these messages in another queue. I would like to store these responses in a generic class because I am storing it in a multimap.
The response class currently is defined as follows
class COutboundMsg
{
public:
enum eTypeHint {
thNone,
thSomeType,
thLast
};
eTypeHint m_TypeHint;
void* m_OutboundData;
COutboundMsg(COutboundMsg::eTypeHint TypeHint, void* data);
};
COutboundMsg::COutboundMsg(COutboundMsg::eTypeHint TypeHint, void* data) :
m_TypeHint(TypeHint),
m_OutboundData(data)
{
}
Now, the current way of working would involve a user to do something like this:
CSomeType* data = new CSomeType();
COutboundMsg(COutboundMsg::thSomeType , (void*) data);
It would be up to the user at the other end to cast the void* back to CSomeType* (using the type hint) and delete it.
It don't like it.
I'd rather have the m_OutboundData contained in an auto_ptr or something and make sure that it deletes itself when done.
Any ideas? Maybe a different approach altogether
Normally polymorphism is used for a system like this; any item that can be put in the Outbound queue derives from QueueItem and the queue contains QueueItem* or a smart pointer to a QueueItem.
Since the items all derive from a common base, you can safely delete the QueueItem* or allow a smart pointer to handle it. This approach also allows you to use dynamic_cast to make sure that the pointer is, in fact, pointing to an object of the type you think it is.
If this approach is possible, be sure to make the QueueItem destructor virtual, otherwise the derived class's destructor won't be called.
shared_ptr stores a deleter to use to delete the object, and so does not depend on the static type of the pointer at the time of deletion. So something like this should do the right thing:
COutboundMsg(eTypeHint TypeHint, shared_ptr<void> msg);
shared_ptr<CSomeType> data(new CSomeType);
COutboundMsg(COutboundMsg::thSomeType, data);
If the set of messages is known before hand (transmit/receive), rather than polymorphism, consider a variant type, I'm taking specifically about boost::variant<>.
The advantage of this approach is that each message is a specific type (I know it seems like you don't want to implement this - however as a long term design feature, I think you'll find this approach extensible) and the variant describes the set of messages, let me show a quick example:
let's say I have two messages
struct Logon{};
struct Logout{};
I define a variant to hold the possible set of messages, at a given time it's only ever one of them..
typedef boost::variant<Logon, Logout> message_type;
Now I can store this in any container, and pass it around like normal, the only difference is that the truly generic way to access them is via visitors, e.g.
struct process : boost::static_visitor<>
{
void operator()(Logon const& cLogon)
{
// do stuff
}
void operator()(Logout const& cLogout)
{
// do stuff
}
};
// method that processes a given message
void processMessage(message_type const& cMsg)
{
// don't know what this message is, that's fine, hand it to the visitor
boost::apply_visitor(process(), cMsg); // the correct overload will be called for the message
}
...I think it's slightly better than void* ;)