简单地说,在说
之间有什么(或有什么)差异class MyClassList : list<MyClass> { };
VS
typedef list<MyClass> MyClassList;
我能想到的唯一优势(以及它引出我这个问题的原因)是,通过派生类,我现在可以轻松地将MyClassList声明为
class MyClassList;
没有编译器错误,而不是
class MyClass;
typedef list<MyClass> MyClassList;
我无法想到任何差异,但这让我想知道,是否存在可以使用简单派生类不能使用的typedef的情况?
或者换句话说,我有什么理由不改变我的所有typedef列表&lt; ...&gt; SomeClassList;到简单的派生类,以便我可以轻松地转发声明它们?
答案 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 ++开发人员应该知道派生并不一定意味着多态性。未通过指向其基类的指针删除的类不需要虚拟析构函数,就像其方法未设计为通过基指针“调用”的类不需要该方法是虚拟的。 简单地说,如果析构函数不是虚拟的,则不要在删除时将该类型视为“多态”。 从这个意义上讲,析构函数与其他虚拟或非虚拟方法没有区别。 如果这个论点必须被认为是强大的,那么,不应该派生所有没有“全虚”方法的类!