typeid.name() 在遍历向量时不会改变.动态转换和 typeid 基类指针 [英] typeid.name() not changing when iterating through a vector. Dynamic cast and typeid a base class pointer

查看:90
本文介绍了typeid.name() 在遍历向量时不会改变.动态转换和 typeid 基类指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

答案:简而言之,使用虚函数!因此,实际上不要将其用作好的设计,而是出于学习目的阅读!

Answer: In short use virtual functions! So don't actually use this as good design, but for learning purposes take a read!

我想首先说我使用的是 C++ 和 Qt我有一个形状指针向量(基类)

I want to start off by saying I am using c++ and Qt I have a vector of Shape pointers (Base class)

doSomething() 不是基类的成员,而是派生类的成员.这就是为什么我使用 dynamic_cast 将 Shape* 获取到 Derived* 以便我可以访问它.我真的只是出于好奇而这样做,但也为了其他人了解 C++ 的类型系统

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();

这里我想遍历向量

    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();
        }
    }

然而,两者都会产生 Square 输出;不是第二个圆圈.我尝试比较 typeid 的内存位置

However Both result in the Square output; not the circle for the second. I tried comparing the memory locations of typeid

像这样:

    &typeid(**tmp) == &typeid(Square)

和圆相同,但 tmp 总是导致上面的情况下的正方形,然后当它紧跟圆时......动态转换是否对整个向量做一些事情我只是错过了 typeid 的一些东西() 有效吗?

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?

这是答案,感谢 user4581301(我也添加了一些东西!):

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();
            }
        }


}

推荐答案

这与 doSomething 作为 virtual 函数一起工作.如果它不是virtual,那么编译本身就会失败(如果Shape 类中没有其他virtual 函数).如果源类型不是多态的,动态转换将失败.

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.

如果是virtual,你不需要做你正在做的事情来确定类型.让多态发挥它的魔力.您可以像这样缩短代码:

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();        
    }
}

这篇关于typeid.name() 在遍历向量时不会改变.动态转换和 typeid 基类指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆