Handles Comparison: empty classes vs. undefined classes vs. void*

半城伤御伤魂 提交于 2019-11-28 01:52:29

Approach #1 is some mid-way between C style and C++ interface. Instead of member functions you have to pass the handle as argument. The advantage of exposed polymorphism is that you can reduce the amount of functions in interface and the types are checked compile time. Usually most experts prefer pimpl idiom (sometimes called compilation firewall) to such interface. You can not use approach #1 to interface with C so better go full C++.

Approach #2 is C style encapsulation and information hiding. The pointer may be (and often is) a pointer to real thing, so it is not over-engineered. User of library may not dereference that pointer. Disadvantage is that it does not expose any polymorphism. Advantage is that you may use it when interfacing with modules written in C.

Approach #3 is over-abstracted C-style encapsulation. The pointer may be really not a pointer at all since user of library should not cast, deallocate or dereference it. Advantage is that it may so carry exception or error values, disadvantage is that most of it has to be checked run time.

I agree with DeadMG that language-neutral object-oriented interfaces are very easy and elegant to use from C++, but these also involve more run-time checks than compile time checks and are overkill when i don't need to interface with other languages. So i personally prefer Approach #2 if it needs to interface with C or Pimpl idiom when it is C++ only.

Approach 3 is not very good at all, as it allows the mixing and matching of handle types that don't actually make sense, any function that takes a HANDLE can take any HANDLE, even if it's compile-time determinable that that is the wrong type.

The downside of Approach 1 is that you have to do a bunch of casting on the other end to their actual types.

Approach 2 isn't that bad, except you can't do any kind of inheritance with it without having to externally query every time.

However, all of this is entirely moot ever since compilers discovered how to implement efficient virtual functions. The approach taken by DirectX and COM is the best- it's very flexible, powerful, and completely type-safe.

It even allows for some truly insane things, like you can inherit from DirectX interfaces and extend it that way. One of the best advantages of this is Direct2D and Direct3D11. They're not actually compatible (which is truly, horrendously stupid), but you can define a proxy type that inherits from ID3D10Device1 and forwards to the ID3D11Device and solve the problem like that. That kind of thing would never even think about being possible with any of the above approaches.

Oh, and last thing: You really, really shouldn't name your types in allcaps.

2 and 3 are slightly less typesafe as they allow to use handles instead of void*

void bluescreeen(HBOOK hb){
  memset(hb,0,100000); // no compile errors
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!