Есть ли обходной путь для того, чтобы сделать член структуры как-то «приватным» в C? - PullRequest
14 голосов
/ 26 марта 2010

Я разрабатываю простую библиотеку на C, для собственного + личного пользования.

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

Есть ли какой-нибудь обходной путь, чтобы скрыть этих участников, чтобы они не были доступны?

Ответы [ 4 ]

15 голосов
/ 26 марта 2010

Обычная техника такова:

/* foo.h */
typedef struct Foo Foo;

Foo *foo_create(...);

void foo_bark(Foo* foo, double loudness);

/* foo.c */
struct Foo {
  int private_var;
};

Вы можете частично скрыть элементы данных, определив Foo в заголовке и FooPrivate в файле .c, таким образом:

struct FooPrivate {
  Foo public_stuff;
  int private_var;
}

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

2 голосов
/ 26 марта 2010

Марсело Кантос уже дал вам ответ. Для получения более подробной информации вы должны посмотреть, как структура FILE эффективно скрыта в большинстве библиотек uderlying.

Вы бы заметили, что структура FILE сама по себе никогда не доступна пользователю, нам доступны только интерфейсы и непрозрачный FILE *.

1 голос
/ 26 марта 2010

Я согласен с Marcelo Cantos, но также предлагаю просто добавить указатель внутри «публичной» структуры, которая указывает на «приватное» содержимое, т.е.

/* foo.h */
typedef struct Bar Bar;
typedef struct Foo 
{
   int public;
   Bar* private;
} Foo;

Foo *foo_create(...);

void foo_bark(Foo* foo, double loudness);

/* foo.c */
struct Bar 
{
  int private_var;
};

Этот подход отчасти напоминает идею "pimpl". Самый простой подход - сделать то, что предложил Марсело Кантос.

1 голос
/ 26 марта 2010

По сути, идея состоит в том, чтобы переименовать переменные структуры с помощью чего-то вроде хеша и пишите функции (которые бы в некотором роде имитировали методы на языках ОО) для доступа к ним. В идеале вы должны иметь указатели на эти функции в вашей структуре, чтобы вы не делали Вызвать внешнюю функцию и передать ей структуру, членов которой вы хотите добавить. Однако синтаксис указателя на функцию, как известно, не является самым красивым. Простой пример, который может прояснить сказанное Марсело:

struct Car {
    int _size;
    char _colour[10];

};

typedef struct Car Car;


int main (int argc, char **argv) {   
    Car *myCar= malloc(sizeof(Car));
    myCar->_size=5; /* accessing it directly just to set up a value, you shold have an
                       accessor function really */

    printf("car size is: %i \n",getCarSize(myCar));
    free(myCar);
}




int getCarSize(Car *myCar) {
     return myCar->_size;
}
...