|
|
Есть способ скрыть реализацию структуры внутри модуля. Например:
|
|
|
|
|
|
```c
|
|
|
|
|
|
/* file.h */
|
|
|
|
|
|
// Только объявление структуры, без определения
|
|
|
struct s;
|
|
|
|
|
|
// Можно создавать функции, которые принимают указатель на такую структуру или возвращают его.
|
|
|
bool s_is_good( struct s* some_struct );
|
|
|
|
|
|
/* Нельзя:
|
|
|
bool s_is_good( struct s some_struct );
|
|
|
Мы не знаем устройство s !
|
|
|
*/
|
|
|
|
|
|
void s_init( struct s** inst );
|
|
|
```
|
|
|
|
|
|
|
|
|
```c
|
|
|
/* file.c */
|
|
|
|
|
|
struct s { int x; }
|
|
|
|
|
|
// Мы знаем внутреннее устройство структуры поэтому можем обращаться к её полям
|
|
|
bool s_is_good( struct s* some_struct ) {
|
|
|
return x > 0;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Только в `file.c` можно работать с полями структуры `struct s`. В других файлах нельзя:
|
|
|
|
|
|
- Создавать переменные типа `struct s`;
|
|
|
- Принимать такую структуру как аргумент функции или возвращать эту структуру по значению из функций.
|
|
|
|
|
|
# Преимущества
|
|
|
|
|
|
- Инкапсуляция: можно как угодно менять порядок полей и их количество, остальная часть программы не заметит этого. Её даже можно не перекомпилировать! Особенно удобно для библиотек.
|
|
|
|
|
|
# Недостатки
|
|
|
|
|
|
- Дополнительный уровень косвенности, надо обращаться по указателю, может плохо сказаться на производительности,
|
|
|
- Неудобство. Например, `init` методы вынуждены принимать указатель на указатель:
|
|
|
|
|
|
```c
|
|
|
/* не файл file.c */
|
|
|
...
|
|
|
struct s* variable = NULL;
|
|
|
s_init( &s ); // теперь s указывает на инициализированный экземпляр структуры struct s
|
|
|
``` |
|
|
\ No newline at end of file |