typedef优于派生类的优点?

时间:2011-09-02 15:22:36

标签: c++ templates forward-declaration

简单地说,在说

之间有什么(或有什么)差异
class MyClassList : list<MyClass> { };

VS

typedef list<MyClass> MyClassList;

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

class MyClassList;

没有编译器错误,而不是

class MyClass;
typedef list<MyClass> MyClassList;

我无法想到任何差异,但这让我想知道,是否存在可以使用简单派生类不能使用的typedef的情况?

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

5 个答案:

答案 0 :(得分:9)

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

typedef只是为现有类型创建别名,因此typedef std::list<MyClass> MyClassList;会创建一个名为MyClassList的“新类型”,现在可以使用如下:

MyClassList lst;

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

答案 1 :(得分:5)

typedef完全用于此目的 - 别名类型名称。它非常惯用,不会让任何熟悉C ++的人感到困惑。

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

std::list没有虚拟析构函数。当通过基类删除时,含义MyClassList不会调用其析构函数。所以这通常不赞成。在您的情况下,您无意将任何成员放在MyClassList中,因此在下一个程序员将​​继承视为添加新成员/覆盖函数等的邀请之前,这将变得没有实际意义。他们可能没有意识到std::list的析构函数不是虚拟的,也没有意识到在某些情况下MyClassList的析构函数不会被调用。

答案 2 :(得分:3)

嗯,typedef只能做它的名字所暗示的,而派生类可能是它的基础的全面改造。因此,如果你将自己限制为“只是”派生(并且不添加任何成员,或覆盖任何内容等),就编译器而言可能没有太大的区别,那么就人类而言可能会有很大的不同关于代码的读者。

有人可能会怀疑“当typedef足够”时,为什么这是派生类?大多数人会认为必须有一个理由,所以你会让代码的未来维护者的生活更加艰难。另一方面,typedef是一个非常具体的工具,不会提出问题。

虽然我们讨论维护的主题,但不要忘记,就像C ++中的大多数事情一样,“只要我们受到纪律处分并且不跨越这条线就没有任何问题”是对灾难的公开邀请。由于编译器无法阻止你,某人有一天会 越过这条线。

答案 3 :(得分:0)

已经提到了很多东西。但重要的是:

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

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

Typedef没有这样的“问题”。

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

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

答案 4 :(得分:0)

typedef是别名,而类是新类型。 在第一种情况下,编译器必须简单地用列表&lt; MyClass&gt;替换MyClassList。 在第二种情况下,MyClassList涉及生成默认构造函数,复制构造函数赋值运算符,析构函数,以及 - 其中使用c ++ 11 - 甚至移动构造函数和移动赋值。 在默认情况下,由于MyClassList没有其他功能,因此优化很可能会将其删除。

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