C ++中的内部typedef - 好风格还是坏风格?

时间:2009-04-17 08:25:09

标签: c++ coding-style typedef

我最近经常发现的事情是声明与该类中特定类相关的typedef,即

class Lorem
{
    typedef boost::shared_ptr<Lorem> ptr;
    typedef std::vector<Lorem::ptr>  vector;

//
// ...
//
};

然后在代码的其他地方使用这些类型:

Lorem::vector lorems;
Lorem::ptr    lorem( new Lorem() );

lorems.push_back( lorem );

我喜欢它的原因:

  • 它减少了类模板引入的噪音,std::vector<Lorem>变为Lorem::vector等。
  • 它用作意图陈述 - 在上面的示例中,Lorem类旨在通过boost::shared_ptr进行引用计数并存储在向量中。
  • 它允许实现更改 - 即如果Lorem需要在稍后阶段被更改为侵入式引用计数(通过boost::intrusive_ptr),那么这对代码的影响最小。
  • 我觉得它看起来更“漂亮”,可以说更容易阅读。

我不喜欢它的原因:

  • 有时会出现依赖问题 - 如果你想在另一个类中嵌入一个Lorem::vector但只需要(或想要)转发声明Lorem(而不是在其头文件中引入依赖)然后你最终不得不使用显式类型(例如boost::shared_ptr<Lorem>而不是Lorem::ptr),这有点不一致。
  • 可能不是很常见,因此难以理解?

我尽量对自己的编码风格保持客观态度,所以最好能得到一些其他意见,这样我就可以稍微剖析一下我的想法。

9 个答案:

答案 0 :(得分:138)

我觉得它很棒,我自己也用它。最好尽可能地限制名称的范围,使用类是在C ++中执行此操作的最佳方法。例如,C ++标准库在类中大量使用typedef。

答案 1 :(得分:13)

  

它作为意图陈述 -   在上面的例子中,Lorem类   是计算参考   通过boost :: shared_ptr并存储在一个   矢量。

这正是所做的。

如果我在代码中看到'Foo :: Ptr',我完全不知道它是一个shared_ptr还是一个Foo *(STL有::指针typedef是T *,记得)或者其他什么。 Esp。如果它是共享指针,我根本不提供typedef,但要在代码中明确使用shared_ptr。

实际上,我几乎没有在Template Metaprogramming之外使用typedef。

  

STL一直都在做这类事情

使用成员函数和嵌套typedef定义的概念的STL设计是一个历史的死胡同,现代模板库使用自由函数和特征类(参见Boost.Graph),因为这些不排除内置 - 从概念建模的类型,因为它使得适应类型不是为给定的模板库的概念设计更容易。

不要将STL作为犯同样错误的理由。

答案 2 :(得分:9)

Typedef是policy based design and traits在C ++中构建的那些,所以C ++中的泛型编程的强大源于typedef本身。

答案 3 :(得分:8)

Typdef绝对是好风格。你所有“我喜欢的理由”都是好的和正确的。

关于你遇到的问题。那么,前瞻宣言不是圣杯。您可以简单地设计代码以避免多级依赖。

你可以在类之外移动typedef,但Class :: ptr比ClassPtr更漂亮,我不这样做。就像命名空间一样 - 事物在范围内保持联系。

有时候我做了

Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map

它可以是所有域类的默认值,也可以是某些类的特殊化。

答案 4 :(得分:3)

STL始终执行此类操作 - typedef是STL中许多类的接口的一部分。

reference
iterator
size_type
value_type
etc...

是所有typedef,它们是各种STL模板类的接口的一部分。

答案 5 :(得分:3)

对此的另一次投票是一个好主意。在编写必须高效的模拟时,我开始这样做,无论是在时间还是空间上。所有值类型都有一个Ptr typedef,最初是一个boost共享指针。然后,我进行了一些分析,并将其中一些更改为一个提升侵入式指针,而无需更改使用这些对象的任何代码。

请注意,这只有在您知道将要使用哪些类并且所有用途具有相同要求时才有效。例如,我不会在库代码中使用它,因为您无法知道何时在库中编写将使用它的上下文。

答案 6 :(得分:2)

目前我正在研究密集使用这些typedef的代码。到目前为止,这很好。

但是我注意到有很多迭代的typedef,定义被分成几个类,你真的不知道你正在处理什么类型。我的任务是总结隐藏在这些typedef背后的一些复杂数据结构的大小 - 所以我不能依赖现有的接口。与三到六级嵌套命名空间相结合,然后它变得令人困惑。

所以在使用它们之前,有一些要考虑的要点

  • 还有其他人需要这些typedef吗?这个类是否被其他类使用了很多?
  • 我是缩短用法还是隐藏课程? (如果隐藏你也可以想到接口。)
  • 其他人是否正在使用该代码?他们是如何做到的呢?他们会认为这更容易还是会变得困惑?

答案 7 :(得分:1)

我建议将这些typedef移到课堂外。这样,您可以删除对共享指针和向量类的直接依赖性,并且只能在需要时包含它们。除非你在类实现中使用这些类型,否则我认为它们不应该是内部typedef。

你喜欢它的原因仍然匹配,因为它们是通过typedef的类型别名来解决的,而不是通过在你的类中声明它们。

答案 8 :(得分:0)

当typedef仅在类本身内使用时(即声明为私有),我认为这是一个好主意。但是,正是由于你给出的原因,如果需要在类外知道typedef,我就不会使用它。在这种情况下,我建议将它们移到课堂外。