问题
Answer: In short use virtual functions! So don't actually use this as good design, but for learning purposes take a read!
I want to start off by saying I am using c++ and Qt I have a vector of Shape pointers (Base class)
Edit: doSomething() is not a member of the Base class but instead a derived class member. Which is why I am using dynamic_cast to get Shape* to the Derived* so that I can access it. I am really doing this just out of curiosity at this point though and for other peoples learning about c++'s type system
#include <vector>
using namespace std;
vector<Shape *> vec;
Where I push back some derived classes of shape
vec.push_back(new Square());
vec.push_back(new Circle());
Ok then I get an iterator to the beginning
vector<Shape *>::iterator tmp = vec.begin();
Here I want to iterate through the vectors
for(;tmp != vec.end(); ++tmp)
{
if(typeid(**tmp).name() == typeid(Square).name())
{
Square * sptr = dynamic_cast<Square *>(*tmp);
sptr->doSomething();
}
else if(typeid(**tmp).name() == typeid(Circle).name())
{
Circle * cptr = dynamic_cast<Circle *>(*tmp);
cptr->doSomething();
}
}
However Both result in the Square output; not the circle for the second. I tried comparing the memory locations of typeid
Like so:
&typeid(**tmp) == &typeid(Square)
and the same for circle but tmp always results in the square for the case above and when ran against the circle right afterwards... Is dynamic cast doing something with the vector as a whole of am I just missing something with how typeid() works?
Edit: Here is the answer, thanks to user4581301 (I also added some thing too!):
#include <iostream>
#include <vector>
#include <typeinfo>
struct Shape
{
virtual ~Shape(){} //Something here must be virtual or pure virtual!
};
struct Circle: Shape
{
void doSomething(){std::cout << "Circle" << std::endl;}
};
struct Square: Shape
{
void doSomething(){std::cout << "Square" << std::endl;}
};
int main()
{
std::vector<Shape *> vec;
vec.push_back(new Square());
vec.push_back(new Circle());
std::vector<Shape *>::iterator tmp = vec.begin();
for(;tmp != vec.end(); ++tmp)
{
if(&typeid(**tmp) == &typeid(Square))
{
Square * sptr = dynamic_cast<Square *>(*tmp);
sptr->doSomething();
}
else if(&typeid(**tmp) == &typeid(Circle))
{
Circle * cptr = dynamic_cast<Circle *>(*tmp);
cptr->doSomething();
}
}
}
回答1:
This works as intended with doSomething
as a virtual
function. If it is not virtual
, then the compilation itself will fail (if there are no other functions in the Shape
class which are virtual
). Dynamic cast will fail if source type is not polymorphic.
If it is virtual
, you need not do what you are doing to determine the type. Let polymorphism do its magic. You can shorten your code like this:
#include <iostream>
#include <vector>
class Shape { public: virtual void doSomething() {std::cout << "In Shape\n";}};
class Circle: public Shape {public: void doSomething() {std::cout << "In Circle\n";}};
class Square: public Shape {public: void doSomething() {std::cout << "In Square\n";}};
int main() {
std::vector<Shape *> vec;
vec.push_back(new Square);
vec.push_back(new Circle);
for(auto tmp = vec.begin();tmp != vec.end(); ++tmp)
{
(*tmp)->doSomething();
}
}
回答2:
For dynamic cast to work, any of the function in base class must be virtual, that mean base class must be used in polymorphic way.
来源:https://stackoverflow.com/questions/53531927/typeid-name-not-changing-when-iterating-through-a-vector-dynamic-cast-and-typ