代码之家  ›  专栏  ›  技术社区  ›  Doug

为什么std::type_info是多态的?

  •  16
  • Doug  · 技术社区  · 14 年前

    有什么原因 std::type_info


    以下是我想出并拒绝的一些想法:

    1. dynamic_cast 到另一个实现定义的派生类型。这可能是原因,但实现添加一个实现定义的成员(可能是虚拟的)似乎同样容易。希望测试这些扩展的程序无论如何都是不可移植的。
    2. delete 一个基指针。但是没有标准的派生类型,用户无法定义有用的派生类型,因为 type_info 删除 荷兰国际集团 指针从来就不是合法的和可移植的。派生类型没有用处,因为它们不能被构造——我知道,对于这种不可构造的派生类型,唯一的用途是在实现 is_polymorphic 类型特征。
    3. 它为使用定制类型的元类提供了可能性-每个真正的多态 class A A__type_info 键入信息 . 也许这样的派生类可以公开调用 new A 以类型安全的方式使用各种构造函数参数,诸如此类。但是制造 多态性本身实际上使得这样的想法基本上不可能实现,因为您必须为您的元类拥有元类,无限期,这是一个问题,如果 键入信息 对象具有静态存储持续时间。也许这是它多态性的原因。
    4. 动态铸造 )到 或者有人认为它很可爱,或者很尴尬 键入信息 不是多态的。但考虑到没有标准派生类型,也没有标准层次结构中的其他类可以合理地尝试交叉转换,问题是:什么?有没有这样的表达法 typeid(std::type_info) == typeid(typeid(A))
    5. 这是因为实现者将创建自己的私有派生类型(正如我相信GCC所做的那样)。但是,为什么要指定它呢?即使析构函数没有被指定为virtual,并且实现者决定它应该是virtual,但实现肯定可以将其声明为virtual,因为它不会更改 键入信息
    6. 这与部分兼容的abi共存的编译器有关,可能是动态链接的结果。也许实现者可以认识到他们自己 键入信息

    最后一个对我来说是目前最有可能的,但它相当弱。

    4 回复  |  直到 14 年前
        1
  •  9
  •   Steve Jessop    14 年前

    我想这是为了方便实现者。它允许他们定义扩展的 type_info 键入信息

    当然,实施可以 声明它是虚拟的,因为它没有 输入信息,所以一个便携程序 不会告诉我 差别。

    #include <typeinfo>
    
    struct A {
        int x;
    };
    
    struct B {
        int x;
    };
    
    int main() {
        const A *a1 = dynamic_cast<const A*>(&typeid(int));
        B b;
        const A *a2 = dynamic_cast<const A*>(&b);
    }
    

    不管是不是 否则,允许第一个动态转换(并计算为空指针),而不允许第二个动态转换。所以,如果 键入信息

    在我看来,将虚拟析构函数放入标准中比以下两种方法都简单:

    a) 请注意,尽管类定义暗示 没有虚拟函数,允许有虚拟析构函数。

    b) 确定可以区分 是否具有多态性,并禁止所有这些。我不知道,它们可能不是非常有用或有效率的程序,但要禁止它们,你必须想出一些标准语言来描述你对正常规则所做的特定例外。

    不过,如果被禁止,那么一个实现可以:

    • 键入信息
    • 派生其所有typeinfo对象
    • 在内部使用它作为所有内容的多态基类

    这将解决我在文章顶部描述的情况, 但是 typeid 表达仍然是 const std::type_info ,因此实现很难定义程序可以 dynamic_cast 去各个目标看看 他们在特定情况下拥有的对象。也许标准希望允许这样做,尽管实现总是可以提供 类型ID static_cast 对某个扩展类将起作用,然后让程序 动态铸造

    总之,据我所知,虚拟析构函数对实现者是潜在的有用的,除去它不会给任何人带来任何好处,除非我们不会花时间去想它为什么会存在;-)

    is_polymorphic 是不可移植的,所以当一个程序可以测试一个类时 多态的,应该是,一致性程序可能无法测试类 不是 多态性,那不应该。我认为,即使这是不可能的,证明这一点,为了从标准中删除一行,是相当大的努力。

        2
  •  9
  •   Armen Tsirunyan    14 年前

    C++标准说 typeid 返回info类型的对象或其实现定义的子类。所以。。。我想这差不多就是答案。所以我不明白你为什么拒绝你的1分和2分。

    第5.2.8节的当前C++标准的第1条:

    静态类型const的左值 std::输入信息(18.5.1)和动态 type const std::type_info或const 实现定义的类派生 从std::键入保留的信息 18.5.1.61)中描述的行为 按左值扩展到 程序。不管 程序末尾的对象是

    这反过来意味着,一个人可以写以下代码是合法的和罚款的: const type_info& x = typeid(expr); 可能需要类型信息是多态的

        3
  •  2
  •   Cheers and hth. - Alf    14 年前

    typeinfo 提供一种比较此类id以实现相等的方法。但是这个设计太笨拙和有限,所以你需要包装 类型信息 类型信息 my own wrapper .

    类型信息

    因此,问题不在于“嗯,为什么会有一个虚拟的析构函数”,而在于,正如我所见,“嗯,为什么设计如此落后,笨拙,不能直接使用”?我把这归结为标准化过程。例如,iostreams也不完全是优秀设计的例子;不是可以模仿的东西。

        4
  •  2
  •   curiousguy    13 年前

    3/它为使用定制类型的元类提供了可能性-每个真正的多态 class A A__type_info ,来源于 type_info . 也许这样的派生类可以公开调用 new A 多态性本身实际上使得这样的想法基本上不可能实现,因为您必须为您的元类拥有元类,无限期,这是一个问题,如果 键入信息 对象具有静态存储持续时间。也许这是它多态性的原因。

    聪明的。。。

    键入信息 键入信息

    推荐文章