Что такое непрозрачное значение в C ++? - PullRequest
30 голосов
/ 04 октября 2010

Что такое "непрозрачное значение" в C ++?

Ответы [ 5 ]

41 голосов
/ 10 марта 2014

«Непрозрачный» на английском языке определяется как «невидимый, непрозрачный». В области компьютерных наук это означает значение, которое не раскрывает никаких деталей, кроме типа самого значения.

Люди часто используют тип C FILE в качестве классического примера, но часто это , а не непрозрачно - подробности раскрываются в stdio.h, чтобы все могли их видеть, и они просто полагаются на пользователя типа, чтобы не возиться с внутренностями. Это нормально, если люди придерживаются правил, передавая такие значения только таким функциям, как fread() и fclose(), но проблема с раскрытием информации заключается в том, что люди иногда (по глупости) начинают полагаться на нее.

Например, glibc публикует свою структуру FILE (как 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.c и prog2.c в один исполняемый файл и запускаете его, вывод:

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

как и следовало ожидать от основной функции.

31 голосов
/ 04 октября 2010

Пример непрозрачного значения: 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 голосов
/ 04 октября 2010

FILE * является хорошим примером непрозрачного значения. Вы не используете это непосредственно; это единственный «шарик», который вы не можете интерпретировать или манипулировать. Вместо этого вы используете набор функций (fopen, fwrite, fprintf и т. Д.), Которые знают, как им управлять.

Непрозрачность таким образом характерна для многих ситуаций (и во многих API), где у вас есть «магический» дескриптор: черный ящик.

2 голосов
/ 04 октября 2010

Это похоже на непрозрачный указатель - значение, которое не хранит данные, которые ваш код может интерпретировать или обеспечивает доступ к данным, а только идентифицирует некоторые другие данные.Типичным примером является дескриптор Win32, такой как HBITMAP дескриптор растрового изображения - вы можете передать его только соответствующим функциям, но вы ничего не можете сделать напрямую с базовым растровым изображением.

1 голос
/ 09 ноября 2013

из Википедия

В информатике непрозрачный тип данных - это тип данных, который не полностью определены в интерфейсе, так что его значения могут быть только манипулировать путем вызова подпрограмм, которые имеют доступ к отсутствующим Информация. Конкретное представление типа скрыто от его пользователи

Типичные примеры непрозрачных типов данных включают дескрипторы ресурсов предоставляется операционной системой для прикладного программного обеспечения.

Некоторые языки, такие как C, допускают объявление непрозрачных записей. (структуры), чьи размеры и поля скрыты от клиента. Единственный вещь, которую клиент может сделать с объектом такого типа, это взять его адрес памяти, чтобы создать непрозрачный указатель.

Если информация, предоставленная интерфейсом, достаточна для определить размер типа, тогда клиенты могут объявлять переменные, поля, и массивы этого типа, назначить их значения и, возможно, сравнить их за равенство. Обычно это касается непрозрачных указателей.

...