我应该避免使用typedef,尝试使用原始名称并在可能的情况下进行转换吗?

时间:2012-11-28 05:39:49

标签: c++ winapi types casting typedef

我不确定这里的词汇,但希望我能让自己理解。

由于我正在使用一种不那么坚如磐石的C ++知识来完成winapi,我发现很多typedef的东西,对我来说,似乎使问题过于复杂,并添加了一件我必须要记住的东西

例如,UINT代替unsigned intHBITMAP结果只是HANDLE,还有很多其他人。

我的问题是,是否可以/应该在可能的情况下替换该类型的更通用版本,并在需要时将其删除(以及这称为什么)?

例如,我想写

  • void SomeFunction(unsigned int some_int) { ... }代替void SomeFunction(UINT some_int) { ... }

  • HANDLE hBMP = LoadImage(...); ImageList_Add(... (HBITMAP) hBMP ...);代替HBITMAP hBMP = ...

这对新手来说是好事,一般来说是不好的做法,还是什么?

5 个答案:

答案 0 :(得分:7)

1)Win32 API实际上是C,而不是C ++。

如果你考虑像MFC或ATL这样的东西,这两者都是“面向对象的”,只有C ++的API,这一区别变得更加重要。而这两个都是仁慈地变得(已成为?)过时了。

2)Microsoft喜欢使用大量的宏和typedef。我不能说这是“好”还是“坏”。这只是生活中的一个事实。如果您在Windows上工作任何时间,它将成为您的第二天性。

3)最重要的是 - 是的:当您使用Microsoft API时,您应该遵循Microsoft惯例。当MSDN页面显示“HANDLE”时使用“HANDLE”是一件好事。类似的建议适用于“LPxxx”,“TRUE”,“FALSE”,“INVALID_HANDLE”,“HRESULT”等等。如果这就是它在MSDN中所说的那么,那就是你应该使用的。

它不仅会使您的代码更具可读性......但是,令人惊讶的是,它还可以防止通过“第二次猜测”“真实类型”而导致的细微错误。

尝试“再次猜测”这些类型。这只是一个坏主意。

遵循标准惯例将使生活更轻松,更安全,更可靠,更便携。

... IMHO

答案 1 :(得分:6)

请不要typedef明显(UINT unsigned int)。相反,typedef传达意义。 UINT并不比unsigned int更好(有些人可能认为它更短,但更严重的是, 更短)。

在我看来,typedef用于长名称(例如typedef的{​​{1}})是可以的,因为它提高了可读性。 std::map<unsigned int, flost>::const_iterator ......不是那么多。

传达特定类型/用途(如UINT)的特定含义的typedef是不错的。在我看来,HANDLE比使用原始HANDLE更好,因为a)我不在乎void*HANDLE,b)它是否传达了它的目的。< / p>

可移植性void*很好(就像32位有符号整数的typedef一样),因为它允许平台/编译器之间更容易的转换。

答案 2 :(得分:4)

  

这对新手,一般的不良做法或什么都有好处?

这是一种不好的做法。您不应该使用实际类型。

typedef通常用于不同平台上的便携性。编译实现。因此,您应该避免使用实际类型而不是typedef的名称。使用实际类型将使您的代码更紧密地耦合到平台和您使用的编译器实现,实际上如果此组合发生更改,它可能无法正常工作。

此外,对于程序员来说,typedefed名称比实际类型更直观,更广为人知,这也是你应该坚持这些名称的另一个原因。

答案 3 :(得分:2)

Typedefs不仅对可移植性有用,而且对将来的校对也有用。如果MicroSoft在某些时候决定UINT应该是typedef而不是unsigned long int,那么使用unsigned int将确保您的代码继续有效。这种类型的变化是不太可能的,特别是对于像MS这样的大公司的代码,但这个想法仍然存在:UINT适用于多种抽象。它们绝不是坏事,但你偶尔可以找到使用不当的例子。如果您使用其他人的API,请始终使用他们的typedefs。他们可能有充分的抽象理由。

答案 4 :(得分:1)

使用typedef有几个原因。

  1. 缩写某些类型:typedef unsigned int UINT
  2. 便携性:typedef int INT64
  3. 可读性:typedef HANDLE HBITMAP
  4. 我宁愿阅读HBITMAP hBitmap = ...而不是HANDLE hBitmap = ...,原因与我(通常)不会写Animal dog = new Dog()的原因相同,因为更具体的可以帮助您的代码的读者和您这里没有丢失任何内容,因为根据Liskov substitution principle,您可以在任何地方使用dog实例,您可以使用Animal实例。

    如果你使用C ++和Boost,你也可以考虑使用BOOST_STRONG_TYPEDEF,这基本上会创建一个简单的类,从而为你提供一个真正的新类型(这意味着你不能像{I}那样混合使用{ {1}}和HANDLE


    您所描述的强制转换并不是真正的强制转换,因为类型相同,HBITMAP只创建别名,而不是新类型。所以,写作

    typedef

    HANDLE hOtherBitmap = /* some code */;

    就像写作

    HBITMAP hBitmap = (HBITMAP) hOtherBitmap;

    int i = /* some value */;