-
ptr_container cast
Hello
Heres the code I have:
Code:
class base {
public:
};
class object : public base {
public:
void somefunc();
};
boost::ptr_vector<base> m_vector;
m_vector.push_back(new object());
boost::ptr_vector<base>::iterator it;
for( it = m_vector.begin(); it != m_vector.end(); ++it ) {
((object*)it)->somefunc();
}
How should I cast iterator to object?
-
Code:
if(object *p = dynamic_cast<object *>(&*it)) {
it->somefunc();
}
Of course, it would be better if there was no need for the cast.
-
Damn.. that looks complicated..
Did you mean p->somefunc(); ?
-
Code:
dynamic_cast<object&>(*it).somefunc();
If you know the cast will succeed, use a static_cast instead of a dynamic_cast. The dynamic_cast will throw an exception if it fails when done on a reference. If you'd rather check for null, use CornedBee's version.
You know this isn't very good design, right?
-
Yeah, I did mean p->, not it->.
-
Im trying to change some code that used std::vector<object*> instead of ptr_container. It uses class polymorphism..
Do you recomment do redesign it and make virtual functions?
-
If you're always casting, that isn't exactly polymorphism. If you're doing a major redesign then you should consider redesigning the classes to use virtual methods. Whether that is appropriate in the end depends on factors like the scale of changes needed to be made, the risk of introducing bugs and regressions, the time it will take to test the changes, and how long you will be able to reap the benefits of the changes after you make them.
BTW, if you choose to leave the original code as is, and it used C style casts, I would stick with static_cast. That is assuming the original code worked relatively well.
-
The class design at the moment looks like:
Code:
class base {
public:
virtual void function() {
//do something
}
};
class object : public base {
virtual void function() {
//do something
}
};
boost::ptr_vector<base> m_vector;
m_vector.push_back(new object());
So how do I call object's function with pointer to base?
Should I do static cast? Or is there any better way?
Maybe the best approach would be to redesign it some different way?
Thanks again for help
-
You just call function. The virtual call will go to the right member without you having to cast to it.
-
The difference between that example and your first example is that your function exists and is virtual in the base class. That's why you don't need a cast here. This code you just posted is the "correct" usage of polymorphism, so no changes are needed.
-
What if I want to call function thats inside base class (look at previous post)?
-
What do you mean? That you want base's implementation? You could to it->base::function(), but that's not very useful. Virtual functions get overridden for a reason.
-
Yeah. Its how the code was designed..
I need to call base's virtual function. Is that unrecommended?
-
The point of the virtual function is for you to have a pointer to the base class and for you to call a function the base class interface. Then, derived classes can override that function so that they control which version is run. The calling code isn't supposed to know which version is run. It isn't even supposed to know if any derived classes exist or not. It calls the function based on the interface, and it is up to the designers of the class to control what gets executed.
In your example, the vector stores a base pointer, but the thing it points to is an object. That means that when you call the virtual function from the base class pointer, the object's version will get implemented.
If you want the base class version to be run, then you need to think about why. Is it because that's how the base class and the object class are supposed to work? If so, fix it there. Make the function not be virtual, or add a new function that does that work.
Is it because the calling code only wants the base class implementation? If so, why does it allow derived classes in the first place?