【问题标题】:Advantages of typedef over derived class?typedef 相对于派生类的优势?
【发布时间】:2011-11-09 06:46:37
【问题描述】:

简单地说,做说之间有什么(或有什么)区别

class MyClassList : list<MyClass> { };

typedef list<MyClass> MyClassList;

我能想到的唯一优势(以及导致我提出这个问题的原因)是,有了派生类,我现在可以轻松地将 MyClassList 声明为

class MyClassList;

没有编译器错误,而不是

class MyClass;
typedef list<MyClass> MyClassList;

我想不出有什么区别,但这让我想知道,是否存在可以使用 typedef 而简单派生类不能使用的情况?

或者换句话说,有什么理由不改变我所有的 typedef list<...> SomeClassList;到简单的派生类,以便我可以轻松地转发声明它们?

【问题讨论】:

  • 该标准禁止使用不完整(前向声明的类型)作为标准容器的类型参数,因此您的第二个示例不正确。
  • @Mark B 你可能是对的,这让我更痛苦的是,如果我不使用派生类,我就不得不改为#include
  • 如果你正确地隔离了你的 typedef,额外的包含应该不会花费你太多(你已经不能转发声明 list,因为它在 std 命名空间中)。

标签: c++ templates forward-declaration


【解决方案1】:

在 C++ 中,is NOT recommended 派生自 STL 容器,所以不要这样做。

typedef 只是为现有类型创建别名,因此 typedef std::list&lt;MyClass&gt; MyClassList; 创建了一个名为 MyClassList 的“新类型”,您现在可以按如下方式使用它:

MyClassList lst;

typedefs 更改为派生类是个坏主意。不要这样做。

【讨论】:

    【解决方案2】:

    typedef 正是为了这个目的——给类型名称起别名。它非常地道,不会让任何熟悉 C++ 的人感到困惑。

    但要解决为什么继承可能不是一个好主意。

    std::list 没有虚拟析构函数。意思是MyClassList 在通过基类删除时不会调用其析构函数。所以这通常是不受欢迎的。在您的情况下,您无意将任何成员放入 MyClassList,因此这成为一个有争议的问题直到下一个程序员将​​继承视为添加新成员/覆盖函数等的邀请。他们可能没有意识到std::list 的析构函数不是虚拟的,也没有意识到在某些情况下MyClassList 的析构函数不会被调用。

    【讨论】:

      【解决方案3】:

      好吧,typedef 只能做它的名字所暗示的事情,而派生类可能是对其基类的全面改造。因此,尽管就编译器而言,如果您将自己限制为“仅”派生(而不添加任何成员或覆盖任何内容等)可能没有太大区别,但就人类而言可能会有很大差异代码的读者很担心。

      有人可能想知道“为什么这是一个派生类,而 typedef 就足够了”?大多数人会认为这一定是有原因的,所以你会让代码的未来维护者变得更加困难。另一方面,typedef 是一个非常具体的工具,不会提出问题。

      虽然我们在讨论维护的话题,但不要忘记,就像 C++ 中的大多数事情一样,“只要我们遵守纪律并且不越过这条线,什么都不会出错”是对灾难的公开邀请.由于编译器不会阻止您,因此总有一天会有人越界。

      【讨论】:

        【解决方案4】:

        已经提到了很多事情。然而,一件大事:

        从一个类型派生不会继承所有的构造函数。

        如果有许多非默认构造函数,则在继承时不会拥有它们(您必须将它们转发给基本构造函数)。

        Typedef 没有这样的“问题”。

        现在,typedef 不会生成唯一的 typeid。如果你想要这样,并且没有继承的开销或其他缺点,请查看 boost:它有一个强大的 typedef 宏,可以生成一个唯一的 typeid:

        http://www.boost.org/doc/libs/1_37_0/boost/strong_typedef.hpp

        【讨论】:

          【解决方案5】:

          typedef 是别名,而类是新类型。 在第一种情况下,编译器必须简单地将 MyClassList 替换为 list。 在第二种情况下,MyClassList 涉及默认构造函数、复制构造函数赋值运算符、析构函数的生成,以及 - 在使用 c++11 的地方 - 甚至移动构造函数和移动赋值。 在默认情况下,由于 MyClassList 没有额外的功能,优化很可能会将它们消灭。

          注意:我发现“不推荐使用非虚拟析构函数派生类”的论点是一个弱论点。 C++ 开发人员应该知道派生并不一定意味着多态性。未通过指向其基的指针删除的类不需要虚拟析构函数,就像其方法未被设计为通过基指针“调用”的类不需要该方法是虚拟的。 简单地说,如果析构函数不是虚拟的,则在删除时不要将该类型视为“多态”。 从这个意义上说,析构函数与其他虚拟或非虚拟方法没有什么不同。 如果这个论点必须被认为是强大的,那么,所有没有“全虚拟”方法的类都不应该被派生!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-10-20
            • 2017-03-19
            • 2010-12-23
            • 2015-07-23
            • 2011-02-26
            • 1970-01-01
            • 2012-05-08
            相关资源
            最近更新 更多