3

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

由于我对 C++ 的了解不够扎实,正在研究 winapi,我发现很多 typedef 的东西,对我来说,似乎使问题过于复杂,并添加了我必须记住的另一件事。

例如,UINT代替unsigned int,HBITMAP结果只是一个HANDLE,还有很多其他的。

我的问题是,我是否可以/应该尽可能替换该类型的更通用版本,并在需要时将其丢弃(以及,这叫什么)?

例如,我想写

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

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

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

4

5 回答 5

7

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

如果您考虑 MFC 或 ATL 之类的东西,它们的区别就变得更加重要,它们都是“面向对象的”、仅限 C++ 的 API。并且这两者都幸运地变得(已经变得?)过时了。

2) 微软喜欢使用大量的宏和 typedef。我不能说这是“好”还是“坏”。这只是生活中的事实。如果您长时间使用 Windows,它将成为您的第二天性。

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

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

不要试图“第二次猜测”这些类型。这只是一个坏主意。

遵循标准约定将使生活更轻松、更安全、更可靠和更便携。

恕我直言...

于 2012-11-28T05:51:30.297 回答
6

请不要typedef明显(即UINTfor unsigned int)。而是typedef传达意义。UINT没有比这更好unsigned int(有些人可能会说它更短,但说真的,它并没有那么短)。

在我看来,一个typedef长名称(如typedeffor std::map<unsigned int, flost>::const_iterator)是可以的,因为它提高了可读性。UINT... 没那么多。

Atypedef为特定类型/用途(如HANDLE)传达特定含义是体面的。HANDLE在我看来,比使用 raw 更好,void*因为 a) 我不在乎是否HANDLE是 a void*,b) 它传达了它的目的。

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

于 2012-11-28T05:48:05.747 回答
4

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

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

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

此外,类型定义的名称比实际类型更直观,更广为程序员所知,这是您应该坚持使用这些名称的另一个原因。

于 2012-11-28T05:48:31.143 回答
2

Typedefs不仅对便携性有用,而且对未来的打样也很有用。如果微软在某个时候决定UINT应该使用 atypedefunsigned long int不是 a ,unsigned int那么 usingUINT将确保您的代码继续工作。这种类型的更改极不可能发生,尤其是对于像 MS 这样的大公司的代码,但这个想法仍然成立:typedefs对多种抽象都有好处。它们绝不是坏事,但你偶尔会发现使用不当的例子。如果您使用其他人的 API,请始终使用他们的typedefs. 他们可能有充分的理由进行抽象。

于 2012-11-28T10:20:07.073 回答
1

使用 typedef 有几个原因。

  1. 缩写一些类型:typedef unsigned int UINT
  2. 可移植性:typedef int INT64
  3. 可读性:typedef HANDLE HBITMAP

我宁愿阅读而HBITMAP hBitmap = ...不是HANDLE hBitmap = ...出于相同的原因(通常)不写Animal dog = new Dog(),因为更具体可以帮助您的代码读者,并且您不会在这里丢失任何内容,因为根据Liskov 替换原则,您可以使用该dog实例您可以在任何地方使用Animal实例。

如果您将 C++ 与 Boost 一起使用,您也可以考虑使用BOOST_STRONG_TYPEDEF,这基本上创建了一个简单的类,因此,为您提供了一个真正的新类型(这意味着您不能像使用HANDLEHBITMAP.


您所描述的铸造并不是真正的铸造,因为类型是相同的, atypedef只创建一个别名,而不是一个新类型。所以,写

HANDLE hOtherBitmap = /* some code */;

HBITMAP hBitmap = (HBITMAP) hOtherBitmap;

就像写作

int i = /* some value */;

int k = (int) i;

于 2012-11-28T10:21:47.843 回答