如果我不使用typedef,尽可能使用基元名称和强制转换

Should I avoid typedef, try to use primitive names and cast when possible?

本文关键字:转换 尽可能 typedef 如果      更新时间:2023-10-16

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

当我用不太扎实的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 = ...

这对新人来说是好的,还是一般的坏做法,还是什么?

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

如果你考虑像MFC或ATL这样的东西,这两种东西都是"面向对象"的,只有C++的API,那么区别就变得更加重要了。幸运的是,这两者都已经过时了。

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

3) 最重要的是——是的:当你使用微软API时,你绝对应该遵守微软的约定。当MSDN页面显示"HANDLE"时使用"HANDLE"是一件好事。类似的建议适用于"LPxxx"、"TRUE"、"FALSE"、"INVALID_HANDLE"、"HRESULT"等。如果MSDN中是这样说的,那么你应该使用它。

它不仅会让你的代码更可读。。。但是,令人惊讶的是,它还可以防止"猜测"真实类型"可能导致的细微错误。

不要试图"猜测"类型。这只是个坏主意。

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

IMHO。。。

请不要使用明显的typedef(即UINT代替unsigned int)。相反,typedef传达意义。UINT并不比unsigned int好(有些人可能会说它更短,但说真的,它并不是短得多的)。

在我看来,长名称的typedef(就像std::map<unsigned int, flost>::const_iteratortypedef)是可以的,因为它提高了可读性。UINT。。。没有那么多。

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

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

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

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

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

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

Typedefs不仅对可移植性很有用,而且对未来的验证也很有用。如果MicroSoft在某个时刻决定UINT应该是unsigned long inttypedef,而不是unsigned int,那么使用UINT将确保您的代码继续工作。这种类型的更改是极不可能的,尤其是对于像MS这样的大公司的代码,但这个想法仍然适用:typedefs适合许多类型的抽象。它们一点也不坏,但你偶尔会发现使用不当的例子。如果您正在使用其他人的API,请始终使用他们的typedefs。他们可能有充分的理由进行抽象。

使用typedef有几个原因。

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

我宁愿读HBITMAP hBitmap = ...,也不愿读HANDLE hBitmap = ...,原因与我(通常)不写Animal dog = new Dog()相同,因为更具体可以帮助代码的读者,而且在这里你不会失去任何东西,因为根据Liskov替换原则,你可以在任何可以使用Animal实例的地方使用dog实例。

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


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

HANDLE hOtherBitmap = /* some code */;

HBITMAP hBitmap = (HBITMAP) hOtherBitmap;

就像写

int i = /* some value */;

int k = (int) i;