假设我有一个按照以下层次结构运行的程序:
我有Human *
的链接列表容器,我正在使用std::list<Human *>::iterator human
进行迭代。以下迭代器可以指向Men
,Women
和Flying Men
。是否有可能,像typeid(*human).name()
之类的东西会返回指向对象所属的类的名称?当我使用typeid.name()
时,我得到class Human *
。
答案 0 :(得分:1)
您可以在对象typeid
本身使用**human
,而不是指针,它始终具有类型Human*
,无论它指向何处。只要Human
是多态的(也就是说,它声明至少一个虚函数),它就会为你提供对象动态类型的类型信息。
请注意,名称不一定是人类可读的,甚至是唯一的;如果指针指向类型3Man
,我的编译器会给出受损的名称Man
,而其他编译器可能会给出其他的恶意。如果你想要一个很好的人类可读名称,你必须声明自己的虚拟成员函数来返回一个。
答案 1 :(得分:1)
在运行时根据类型检查选择执行路径错误,因为它将知识放在不应该的位置,并且因为所有检查都必须使用新的扩展,因此更难添加新类型输入id。
相反,定义一个接口,允许所有需要它的类型创建自己的版本。这是一个可编辑的例子,你可以复制和玩。请注意,添加应序列化的新类型不会更改现有类中的任何代码,也不需要新的测试。并且,作为奖励,所有内容都在编译时进行类型检查,因此无法使用错误类型的对象添加调用。
#include <iostream>
#include <list>
#include <boost/foreach.hpp>
class Output {
public:
// Whatever operations needed
int Write(int value) {
std::cout << value << std::endl;
return 0;
}
};
class Human {
public:
virtual ~Human() {}
virtual int Serialize(Output& output) = 0;
};
class Men : public Human {
public:
int Serialize(Output& output) {
return output.Write(17);
}
};
class Women : public Human {
public:
int Serialize(Output& output) {
return output.Write(42);
}
};
int main(int argc, char* argv[]) {
Output output;
Men men1;
Men men2;
Women women1;
Women women2;
std::list<Human*> toSerialize;
toSerialize.push_back(&men1);
toSerialize.push_back(&women1);
toSerialize.push_back(&men2);
toSerialize.push_back(&women1);
BOOST_FOREACH(Human* human, toSerialize) {
human->Serialize(output);
}
return 0;
}
答案 2 :(得分:0)
没有。 Typeinfo是您将获得的最佳反映。如果你真的需要这个,请创建一个返回正确名称的虚拟成员函数。
答案 3 :(得分:0)
是的,但您的课程必须具有虚拟功能。最好的地方是使用虚拟析构函数,因为它很可能需要尽早而不是迟到。
另请注意,typeid
未定义为您提供可读名称。如果它与你目前的目标编译器有关,那很好。如果没有,您可能需要添加像const std::string &className() const
这样的虚拟函数来获得您想要的内容。