pax*_*blo 42

"不透明"用英语定义为"不能透视;不透明".在计算机科学中,这意味着一个值,除了值本身的类型之外,没有显示任何细节.

人们经常使用C类型FILE作为经典示例,但通常这不是不透明的 - stdio.h任何人都可以看到细节,他们只是依靠类型的用户来摆弄内部.只要人们遵守规则,只将这些价值传递给类似的功能,那就没问题了fread(),fclose()但是泄露信息的问题是人们有时(愚蠢地)开始依赖它.

例如,glibc发布其FILE结构(as struct _IO_FILE),libio.h以便该类型在技术上不是不透明的.

请注意前面部分定义:"不能"而不是"不愿意".不透明度要求隐藏信息,而不是仅仅颁布"绅士协议"而不使用它.

正确完成的不透明指针应该不会显示除类型名称本身之外的任何信息,您可以相对容易地在C中实现它.考虑以下prog2.h用于获取和释放xyzzy对象的头文件:

struct xyzzy;
struct xyzzy *xyzzyOpen (void);
void xyzzyClose (struct xyzzy *fh);
Run Code Online (Sandbox Code Playgroud)

这就是代码的客户端看到的所有内容,一个不完整的类型struct xyzzy以及一些用于分配和释放该类型对象的函数(它们不会prog2.c在下面详细介绍).请注意,指向不完整类型的指针很好但是您无法实例化该类型的对象,因为您不知道其内部.所以代码:

struct xyzzy myvar;
Run Code Online (Sandbox Code Playgroud)

会导致错误:

prog1.c: In function ‘main’:
prog1.c:3:15: error: storage size of 'myvar' isn't known
Run Code Online (Sandbox Code Playgroud)

现在,您可以非常愉快地使用程序中的这些函数,prog1.c 而无需了解结构的内部结构:

#include "prog2.h"
int main (void) {
    //struct xyzzy myvar;             // will error
    struct xyzzy *num1 = xyzzyOpen();
    struct xyzzy *num2 = xyzzyOpen();
    struct xyzzy *num3 = xyzzyOpen();
    xyzzyClose (num1);
    xyzzyClose (num3);                // these two intentionally
    xyzzyClose (num2);                //   reversed.
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

并且调用的实现prog2.c,实际上控制并知道内部,因此可以非常自由地使用它们:

#include <stdio.h>
#include <stdlib.h>
#include "prog2.h"

struct xyzzy { int payload; };
static int payloadVal = 42;

struct xyzzy *xyzzyOpen (void) {
    struct xyzzy *plugh = malloc (sizeof (struct xyzzy));
    plugh->payload = payloadVal++;
    printf ("xyzzyOpen payload = %d\n", plugh->payload);
    return plugh;
}

void xyzzyClose (struct xyzzy *plugh) {
    printf ("xyzzyClose payload = %d\n", plugh->payload);
    free (plugh);
}
Run Code Online (Sandbox Code Playgroud)

printf呼叫在那里只是为了表明它可以使用内部,你可能会想从添加的返回值的检查malloc在生产就绪代码,但是这是不相关的这个例子的目的.

当您编译prog1.cprog2.c运行单个可执行文件并运行它时,输出为:

xyzzyOpen payload = 42
xyzzyOpen payload = 43
xyzzyOpen payload = 44
xyzzyClose payload = 42
xyzzyClose payload = 44
xyzzyClose payload = 43
Run Code Online (Sandbox Code Playgroud)

正如你对主要功能所期望的那样.

  • 尽管我们有分歧,但还是投了赞成票,因为当它放在它自己的时候,它确实*突出了一个有趣的角度.我不同意其必要性并不意味着我不能对其优点进行良好的表述.;-)没有难过的感情,并且玩得开心. (7认同)
  • @DevSolar,如果我们都同意的话,我会无聊无知:-)干杯. (6认同)
  • @JimBalter:虽然paxdiablo和我自己都没有真正弄清楚这一点,但是很明显`FILE`是否不透明(根据paxdiablo和你的定义)*完全取决于实现*(因为你可以随时申请paxdiablo的技术也是"文件".你可能还会注意到,虽然不同意这个问题,但是paxdiablo和我能够这样做而不会变得粗鲁并且互相称呼"错误"或"顽固".另外,我的回答早于这一点,所以我不得不"承认"这里. (3认同)
  • 这是正确的答案.DevSolar是完全错误的... FILE不是不透明的,它的内部对于用户是可见的,就像任何其他结构一样,人们已经知道利用它(后来当实现改变或代码被移植到另一个实施).可以从源复制结构定义然后转换不透明指针的概念,虽然技术上是正确的,但只是顽固地拒绝承认正确的答案. (2认同)

Dev*_*lar 33

不透明值的一个例子是FILE(来自C库):

#include <stdio.h>

int main()
{
    FILE * fh = fopen( "foo", "r" );
    if ( fh != NULL )
    {
        fprintf( fh, "Hello" );
        fclose( fh );
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

你得到一个FILE指针fopen(),并将其用作其他函数的参数,但你从不打扰它实际指向的内容.

  • 它实际上是一个指针并不重要; 不透明指针只是恰好是指针的不透明值. (4认同)
  • 实际上,opaque与你是否与其指向的内容无关,这与用户选择无关.一个真正的不透明指针_reveals_没有细节.如果查看stdio.h并定义了结构,那么FILE不是不透明的. (3认同)
  • @paxdiablo:语言学.没有操作需要实际访问`FILE`的*值*,你只需传递它.如果您无法在标题中找出其内容,您仍然可以对其进行逆向工程,但您不必这样做,因为它的结构并不重要.图书馆实施者可以在没有任何进一步通知的情况下改变其内部,并且它不应该有所作为.(当然,除非你*破解了它的内部结构.)不要将访问的易用性与可访问性混为一谈.C++`private`数据成员也不是"隐形"...... (3认同)
  • @SriHarshaChilakapati:您可以*用实际语言标准确认*.不要过分信任讲师; 他们不时被认为是错的.;-) (2认同)