Typedefing指针类型

时间:2010-12-05 00:57:18

标签: c++ c pointers typedef

我一直在阅读SO,并且遇到了以下问题,这些问题涉及为什么typedefing指针类型不好。

Opaque C structs: how should they be declared?Const-correctness and immutable allocated objects

我想知道是否有人可以扩展并解释为什么typedefing指针类型很糟糕,并且可能提供一些可能发生错误的示例。

另外,如果typedefing指针类型确实是禁忌,那么为什么Win32 API会这样做呢?在Win32中HANDLE(以及有效的句柄类型)的类型定义为void *

8 个答案:

答案 0 :(得分:11)

约翰内斯已经说过typedef指针本身并不坏,我同意。

一些指导原则,基于我对主观清晰度的主观意见。可维护性:

  • 通常执行 typedef函数指针类型。

    原因:
    函数指针声明可能会变得非常混乱&不可读。

  • 一般 typedef原始对象指针,其中指针类型不是抽象(例如,当你只需要一个“指向 T的指针“)。

    原因1:
    更明显的是,Foo*Foo const*FooPtr更明显。使用名称,您必须查找名称以查看其定义的名称。也许它是一些智能指针,也许它是指向const的指针,无论如何;这个名字让你不必要地去别处看。

    原因2:
    一些程序员对consttypedef'ed指针类型的组合感到困惑。例如。在Microsoft代码中,我已经多次看到FooPtr const的等价物,程序员显然认为这意味着Foo const*。但它没有,这意味着Foo* const

  • 一般来说 typedef当指针类型是一个抽象时,它也是一个原始对象指针,一个指针类型,可以想象将来可以用其他类型替换,比如例如HANDLE

    原因: 与使用命名常量相同:如果没有正确的名称,搜索和替换可能会更改意味着其他内容的事件,并且无法更改未以“正确”方式表达的事件。

然而,与几乎所有类型的风格一样,赞成和反对的论据相当薄弱,因此最终的选择归结为个人偏好,编码标准,同事的意见等等。

鉴于自由选择,以上通常是我选择的。但在特殊情况下,我偏离了这些准则/规则。与良好的艺术一样,那些熟悉规则并且知道何时打破它们的人会产生良好的代码......

干杯&第h。,

答案 1 :(得分:6)

typedef指针类型并不客观。编写得很好的代码使用它来键入指向处理函数类型的指针,这对于像HANDLER这样的事情也很常见。

这可能是一个人的个人意见,这是不好的,但它肯定不是广为接受的意见。我一个人根本不同意这个意见。我自己很少使用这个选项,但我仍然认为它不是“坏”。

答案 2 :(得分:2)

如果要在库的公共接口上提供句柄类型,请使用typedef。不要将其公开为struct foo*。句柄是否是指针纯粹是一个实现细节......它总是表现为指针,但是将索引用于某些内部数据结构通常更方便。

答案 3 :(得分:1)

Windows和POSIX都有typedef指针,但这并不意味着它总是很好的做法。它主要是隐藏实现细节,但这并不总是一件好事。

答案 4 :(得分:1)

通过“typedefing”指针,你实际上是在遵循C实践,而不是C ++实践。在C中为了隐藏实现细节,通常使用typedef,因为它允许某种基本形式的数据隐藏:

typedef struct somestruct* pointer;

void foo(pointer p);

如果以后改为

typedef struct someotherstruct* pointer; 

void foo(pointer p);

您不必更改使用指向“struct someotherstruct *”的所有函数参数,您甚至可以通过在someotherstruct中添加新字段来伪造多态性。

在C ++中,还有其他方法可以更好地实现上述目标。

编辑:也许数据隐藏在这里是一个太强大的词,但它允许你改变使用指针的指针的实现而不破坏现有的代码(如果正确的话)

答案 5 :(得分:0)

如果不清楚什么是指针,什么不是你可能有内存问题,windows typedefs HANDLE as void *因为它们提供了获取和清理句柄的方法。这不是一件坏事,但如果很多人正在开展一个项目,我会建议不要这样做。这主要是一个清晰度问题。

答案 6 :(得分:0)

使用指针typedef没有任何问题,但你需要记住,typedef不定义新类型(比如类),但为现有类型定义别名。这意味着如果你有两个typedef是同一类型的别名,你不能依赖C ++的类型检查来防止你无意中混淆它们。

答案 7 :(得分:0)

有时您需要向前声明一个结构指针,以便编译函数声明。你不能只是前向声明结构。

typedef struct my_struct * my_struct_ptr;

extern void my_func( my_struct_ptr pointer );

typedef struct _my_struct { int a_field; } my_struct;

(使用st20cc 3.63)