2010-05-05 250 views
0

这是我的代码:如何检查派生类中对象的类型名称?

代码
class Base { /* something */ }; 
class Derived : public Base { /* something */ }; 
vector<Base*> v; // somebody else initializes it, somewhere 
int counter = 0; 
for (vector<Base*>::iterator i=v.begin(); i!=v.end(); ++i) { 
    if (typeof(*i) == "Derived") { // this line is NOT correct 
    counter++; 
    } 
} 
cout << "Found " << counter << " derived classes"; 

一号线是不正确的。我应该如何正确书写它?提前谢谢了!

回答

5

typeid的名称是实现定义的,你不应该对它们做出假设。不过,你可以比较两个typeid的。

if typeid(**i) == typeid(Derived) 

通常会被认为是不好的设计(但如果目的只是写一个不是很实用程序来算的衍生的实例,它只是罚款)。

注意,这也需要基地有虚表(虚函数和/或析构函数),因为非多态类型只是没有动态类型的typeid检查(也就是,他们都成为Base实例就typeid而言)。

如果你没有任何虚拟功能,那么你需要自己模拟它。例如,如果你喜欢字符串比较,并且不介意开销,那么在Base中添加一个字段,每个类型将在其构造函数中填写并进行比较。否则,使用独特整体识别每个亚型等

+0

谢谢,现在一切都很明确:) – yegor256 2010-05-05 15:41:45

+0

我发现这个链接:http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/boost_typetraits/reference/is_same.html。看起来像这个库可以帮助.. – yegor256 2010-05-05 16:51:22

+0

@Vincenzo:这只在编译时才有效。在编译时,向量中的所有静态类型都是相同的。你需要一个运行时机制。 – UncleBens 2010-05-05 17:35:54

0

我认为typeof仅适用于C#。

的SO发布 “How to typeof in C++” 可能是使用的...

更新: This可能是使用:

typeof运算符,据我所知,是一个GCC 扩展。从GCC 3.2.3开始,它不再适用于模板对象 。 错误报告: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9459

版本的变化: http://www.gnu.org/software/gcc/gcc-3.2/changes.html

目前GCC似乎有一个非常 很难确定,即使在合法的情况下 的 模板函数的类型......

我认为GCC支持__typeof__运营商。

正如其他人所说,我想你可以使用typeid作为替代。

+0

感谢您的建议,但问题是我如何做比较。我不需要typeid信息。我需要能够将它与一个字符串进行比较。谢谢 – yegor256 2010-05-05 15:33:41

0

看看typeid运营商。

一般来说,使用它是不好的主意。

+0

亚历克斯,有什么好的选择呢?谢谢 – yegor256 2010-05-05 15:31:48

+0

使用dynamic_cast比较好,但无论如何,通常你不需要知道对象的确切类型。所有的逻辑都可以通过虚拟功能来实现。但是,有时您需要知道确切的类型,在这种情况下,您必须使用typeid。 – a1ex07 2010-05-05 16:04:52

5

使用的dynamic_cast:

if (dynamic_cast <Derived*>(*i)) { 
    counter++; 

对于这个工作,你需要给你的基类的至少一个虚拟功能 - 它确实需要一个虚析构函数无论如何。

0

您可以使用typeid(包括<typeinfo>):

if (typeid(**i) == typeid(Derived)) 

,或者您可以使用动态转换:

if (dynamic_cast<Derived*>(*i) != 0) 

但两者的代码通常应该支持虚拟功能来避免被调用并被覆盖以对每种类型执行适当的操作。

+0

你确定最后一点建议适用于此。为什么应该写一个虚拟函数来模拟已经存在的相同RTTI(除了留下更少的错误空间外)? – UncleBens 2010-05-05 15:37:22

+0

@UncleBens:我如何确定我们所拥有的只是玩具示例代码?但是我确信在绝大多数用例中,是的,我的最后一点建议是适用的。即使在玩具示例中,也可以为虚拟'isDerived'函数与'count_if'一起使用。 – 2010-05-05 15:42:06

+0

感谢您的评论,康拉德!但是,我没有基类中的任何虚函数。 – yegor256 2010-05-05 15:42:41

0

我想你想:

for (...) { 
    if (dynamic_cast<Derived*>(*i)) { 
    counter++; 
    } 
} 

的dynamic_cast <>试图将基类指针转换为派生类指针。如果对象是派生类型(或其子类),则返回正确的指针。如果不是该派生类型,则返回'nil'来表示转换不能成功完成。