Typedefing pointer types
I've been reading around SO and have come across the following questions which touch on why typedefing pointer types is bad.
Opaque C structs: how should they be declared? and Const-correctness and immutable allocated objects
I was wondering if someone could expand and explain why typedefing pointer types is bad and perhaps provide some examples of where errors might occur.
Als开发者_如何学Goo, if typedefing pointer types is indeed a no-no, then why does the Win32 API do it? in Win32 HANDLE
(and effectively Handle types) are typedef'd as a void *
.
Johannes has already remarked that typedef
'ing pointers is not inherently bad, and I agree.
Some guidelines, based on my subjective opinion of clarity & maintainability:
Generally do
typedef
function pointer types.Reason:
Function pointer declarations can get really messy & unreadable.Generally don't
typedef
raw object pointers where the pointer type is not an abstraction (e.g., when you just need a "pointer to T").Reason 1:
It's more clear to seeFoo*
orFoo const*
than, say,FooPtr
. With the name you have to look up the name to see what it's defined as. Perhaps it's some smart pointer, perhaps it's a pointer toconst
, whatever; the name makes you needlessly look elsewhere.Reason 2:
Some programmers are confused by the combination ofconst
andtypedef
'ed pointer types. E.g. in Microsoft code I've seen the equivalent ofFooPtr const
many times, where the programmer evidently thought it meantFoo const*
. But it doesn't, it meansFoo* const
.Generally do
typedef
also a raw object pointer when the pointer type is an abstraction, a pointer type that conceivably can be replaced with some other type in the future, like e.g.HANDLE
.Reason: The same as for using named constants: without a proper name a search and replace can change occurrences that mean something else, and can fail to change occurrences that are not expressed in the exact "right" way.
However, as with nearly all kinds of style, the arguments pro and con are pretty weak, and so the choice in the end boils down to personal preference, coding standards, co-workers' opinions, and so on.
Given a free choice the above is generally what I'd choose. But I have deviated from those guidelines/rules in special cases. As with good art, good code is produced by those who know the rules well enough to also know when to break 'em…
Cheers & hth.,
It's not objectively bad to typedef pointer types. Much well written code uses it to typedef pointer to handler function types and it's also common for things like HANDLER
.
It may be one's personal opinion that it's bad, but it definitely isn't well-accepted opinion. I for one don't agree with that opinion at all. I myself use that option more seldom, but I still don't think it's "bad".
If you intend to provide a handle type at the public interface to your library, use a typedef. Do not expose it as struct foo*
. Whether a handle is a pointer or not is purely an implementation detail... it will always act as if it is a pointer, but it is often more convenient to use an index into some internal data structure.
Both Windows and POSIX have typedef'ed pointers, but that doesn't mean it's always good practice. It's mostly to hide implementation details, but that's not always a good thing.
By "typedefing" a pointer you effectively are following C practice and not C++ practice. In C in order to hide implementation details, a typedef is often used as it allows for a certain rudimentary form of data hiding:
typedef struct somestruct* pointer;
void foo(pointer p);
if later changed to
typedef struct someotherstruct* pointer;
void foo(pointer p);
you don't have to change all function parameters that use the pointer to "struct someotherstruct*" you can even fake polymorphism with this by adding new fields in someotherstruct.
In C++ there are other ways to achieve the above in a better way.
edit: maybe data hiding is a too strong word here but it allows you to change the implementation of the pointer that uses the pointer without breaking existing code (if done right)
Well if it's not clear what is a pointer and what isn't you may have memory issues, windows typedefs HANDLE as void * because they provide methods for getting and cleaning up handles. It's not a bad thing to do but if many people are working on a project I would recommend against it. It's mostly a clarity issue.
There's nothing wrong with using pointer typedefs but you need to keep in mind that typedefs do not define new types (like classes do) but define aliases for existing types. This means that if you have two typedefs which are aliases of the same type, you can't rely on C++'s type checking to prevent you from inadvertently mixing them up.
Sometimes you need to forward-declare a structure pointer for a function declaration to compile. You can't just forward-declare the structure.
typedef struct my_struct * my_struct_ptr;
extern void my_func( my_struct_ptr pointer );
typedef struct _my_struct { int a_field; } my_struct;
(using st20cc 3.63)
精彩评论