C ++中的不透明值是什么?

时间:2010-10-04 09:50:49

标签: c++ language-agnostic terminology

C ++中的“不透明值”是什么?

5 个答案:

答案 0 :(得分:41)

“不透明”在英语中定义为“无法透视;不透明”。在计算机科学中,这意味着一个值,除了价值本身的类型之外,没有任何细节。

人们经常使用C类型FILE作为经典示例,但通常不透明 - 详细信息在stdio.h中显示,任何人都可以看到,他们只是依赖对类型的用户不要捏造内部。只要人们遵守规则,只将这些值传递给fread()fclose()这样的函数,那就没问题,但揭示信息的问题在于人们有时(愚蠢地)开始依赖它。

例如,glibcFILE中发布其struct _IO_FILE结构(libio.h),因此该类型在技术上不透明。

请注意前面部分定义:“不能”而不是“不愿意”。不透明度要求隐藏信息而不是仅仅制定一个“绅士的同意”不使用它。

不正确的不透明指针应该显示除了类型名称本身之外的 no 信息,你可以相对容易地在C中实现它。请考虑以下头文件prog2.h以获取和释放xyzzy个对象:

struct xyzzy;
struct xyzzy *xyzzyOpen (void);
void xyzzyClose (struct xyzzy *fh);

这是代码的客户端看到的所有内容,一个不完整的类型struct xyzzy以及一些用于分配和释放该类型对象的函数(他们无法查看下面详述的prog2.c)。请注意,指针到一个不完整的类型是可以的,但你不能实例化那种类型的对象,因为你不知道它的内部。所以代码:

struct xyzzy myvar;

会导致错误:

prog1.c: In function ‘main’:
prog1.c:3:15: error: storage size of 'myvar' isn't known

现在,您可以非常高兴地使用程序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;
}

调用的实现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);
}

printf调用只是为了表明它可以使用内部结构,并且您可能希望在生产就绪代码中添加来自malloc的返回值的检查,但这不相关为了这个例子的目的。

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

xyzzyOpen payload = 42
xyzzyOpen payload = 43
xyzzyOpen payload = 44
xyzzyClose payload = 42
xyzzyClose payload = 44
xyzzyClose payload = 43

正如您对主要功能所期望的那样。

答案 1 :(得分:31)

不透明值的示例是FILE(来自C库):

#include <stdio.h>

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

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

答案 2 :(得分:2)

这类似于opaque pointer - 一个值,它不存储您的代码可以解释或提供数据访问的数据,但只识别其他一些数据。一个典型的例子是Win32句柄,如HBITMAP位图句柄 - 你只能将它传递给相关的函数,但你不能直接对底层的位图做任何事情。

答案 3 :(得分:2)

FILE *是不透明值的一个很好的例子。你不直接使用它;它是一个你无法解释或操纵的“blob”。相反,你使用一组知道如何操纵它的函数(fopen,fwrite,fprintf等)。

以这种方式不透明在许多情况下(以及在许多API中)都是常见的,在这种情况下你有一个“神奇”的句柄:黑盒子。

答案 4 :(得分:1)

来自Wikipedia

  

在计算机科学中,不透明数据类型是一种数据类型   在接口中未完全定义,因此其值只能是   通过调用有权访问缺失的子例程来操纵   信息。该类型的具体表示是隐藏的   其用户

     

不透明数据类型的典型示例包括资源句柄   由操作系统提供给应用软件。

     

某些语言(如C)允许声明不透明记录   (结构),其大小和字段对客户端隐藏。唯一的   客户端可以对这种类型的对象做的事情是采取   它的内存地址,用于生成不透明的指针。

     

如果界面提供的信息足够   确定类型的大小,然后客户端可以声明变量,字段,   和该类型的数组,分配它们的值,并可能进行比较   他们是平等的。这通常是不透明指针的情况。