Подтвердить что ты не робот

Что такое непрозрачное значение?

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

4b9b3361

Ответ 1

Пример для непрозрачного значения 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

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

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

Например, glibc публикует структуру FILE (как struct _IO_FILE) в libio.h, поэтому тип не является технически непрозрачным.

Обратите внимание, что часть определения на фронте: "не способна", а не "не желает". Непрозрачность требует, чтобы информация скрывалась, а не просто принимала "джентльменское соглашение", чтобы не использовать ее.

Непрозрачные указатели, сделанные правильно, не должны раскрывать никакой информации, отличной от самого имени типа, и вы можете реализовать это на С относительно легко. Рассмотрим следующий заголовочный файл 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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

из Wikipedia

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

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

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

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