typedef相对于派生类的优势是什么?

7

简单来说,做say的差别(或者是否有差别)是什么?


请确认是否需要翻译其他内容。
class MyClassList : list<MyClass> { };

vs

typedef list<MyClass> MyClassList;

我能想到的唯一优势(也是我提出这个问题的原因)就是使用派生类后,我现在可以轻松地将MyClassList作为前向声明:

class MyClassList;

没有编译错误,而不是

class MyClass;
typedef list<MyClass> MyClassList;

我想不出任何区别,但这让我想知道,在哪些情况下typedef可以被使用而简单的派生类不能?
换句话说,是否有任何理由我不应该将所有的typedef list<...> SomeClassList更改为简单的派生类,以便我可以轻松地前向声明它们?

标准禁止使用不完整的(前向声明类型)作为标准容器的类型参数,因此您的第二个示例是不正确的。 - Mark B
@Mark B 你可能是对的,这让我感到更加痛苦,因为如果我不使用派生类,我就被迫使用 #include。 - MerickOWA
如果您正确隔离了typedef,那么额外的包含文件成本应该不会太高(因为您已经无法前向声明list,因为它在std命名空间中)。 - Mark B
5个回答

9

C++中不建议从STL容器派生,因此请不要这样做。(参考资料)

typedef只是为现有类型创建一个别名。例如typedef std::list<MyClass> MyClassList;会创建一个名为MyClassList的“新类型”,您可以按照以下方式使用它:

MyClassList lst;

将您的typedef更改为派生类是不好的做法,请勿这样做。


5
typedef就是为此目的而设计的——用于别名类型名称。这非常惯用,不会让任何熟悉C++的人感到困惑。
但是要解释为什么继承可能是一个坏主意。
std::list没有虚拟析构函数。这意味着当通过基类删除时,MyClassList的析构函数不会被调用。因此,通常应该避免这样做。在您的情况下,您没有打算在MyClassList中放置任何成员,因此这变得无关紧要,直到下一个程序员将继承视为添加新成员/覆盖函数等的邀请。他们可能没有意识到std::list的析构函数不是虚拟的,并且可能没有意识到在某些情况下MyClassList的析构函数不会被调用。

3
好的,一个typedef只能做它名字所暗示的事情,而一个派生类可能是其基类的全面改变。因此,如果你限制自己“仅”派生(不添加任何成员或覆盖任何内容等),则在编译器方面可能没有太大区别,但对于代码的人类读者来说可能会有很大的区别。
有人可能会想:“既然typedef就足够了,为什么要用派生类呢?”大多数人会认为一定有原因,这会让代码未来的维护者的工作更加困难。而typedef是一个非常具体的工具,不会引起问题。
另外,在维护方面,不要忘记,正如C++中的大多数东西一样,“只要我们有纪律,不越过这条线,就不会出现问题”的想法是灾难的敞开邀请。由于编译器无法阻止您,因此总有一天,某个人会越过这条线。

0
提到了很多事情,但有一件大事:
从类型派生并不继承所有构造函数。
如果有许多非默认构造函数,则在继承时您将无法使用它们(您必须将它们转发到基础构造函数)。
typedef没有这样的“问题”。
现在,typedef不会生成唯一的typeids。如果您想要这样做,并且不想具有继承的开销或其他缺点,请查看boost:它具有生成唯一typeid的强typedef宏:

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


0

typedef 是一个别名,而 class 则是一个新类型。 在第一种情况下,编译器只需将 MyClassList 替换为 list<MyClass>。 在第二种情况下,MyClassList 包括默认构造函数、复制构造函数赋值运算符、析构函数,以及 - 在使用 c++11 时 - 移动构造函数和移动赋值运算符的生成。 在默认情况下,由于 MyClassList 没有额外的功能,优化很可能会将它们清除。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接