Правильно скрывая функции от внешнего контекста модуля - PullRequest
0 голосов
/ 06 февраля 2020

Я пытаюсь реализовать скрытие информации в C ОО. Поскольку C, очевидно, не предоставляет модификаторов доступа, таких как publi c, закрытых и защищенных, я смог найти решение, которое заключается в определении абстрактного типа данных (какие атрибуты не должны быть видны снаружи) в *. c file и поместить в соответствующий заголовочный файл typedef, который относится только к этому новому типу данных.

Заголовочный файл также содержит прототипы моих publi c функций и поэтому работает как интерфейс publi c этого типа данных. Есть также еще один заголовочный файл, в котором перечислены защищенные функции, которые я не хочу видеть в нормальных условиях. Файл *. c содержит реализацию всех функций, включая те, которые не указаны ни в заголовочных файлах. Это мои личные функции.

LinkedList.h

#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_

typedef struct LinkedList LinkedList;

LinkedList* newLinkedList();

#endif

LinkedList_protected.h

#ifndef LINKEDLIST_PROTECTED_H_
#define LINKEDLIST_PROTECTED_H_

#include "Node.h"
#include "LinkedList.h"

Node* getFirstNode(LinkedList* self);

Node* getLastNode(LinkedList* self);

#endif

LinkedList. c

#include "LinkedList.h"
#include "LinkedList_protected.h"
#include "Node.h"

// PRIVATE

struct LinkedList {

    Node* first;
    Node* last;
    unsigned int nodesNo;

};

void privateTest() {

    printf("Test");

}

// PROTECTED

Node* getFirstNode(LinkedList* self) {

    return self->first;
}

Node* getLastNode(LinkedList* self) {

    return self->last;

}

// PUBLIC

LinkedList* newLinkedList() {

    LinkedList* self = malloc(sizeof(LinkedList));

    self->first = NULL;
    self->last = NULL;

    self->nodesNo = 0;

    return self;

}

Кажется, это работает: попытка получить доступ к атрибутам LinkedList в другом модуле дает мне ошибку («разыменование указателя на неполный тип»), что я и хотел. Однако обращение к закрытой или даже защищенной функции просто дает мне предупреждение «неявное объявление». Это почему? Должен ли я беспокоиться об этом? Кроме того, безопасно ли это решение и можно ли его улучшить?

1 Ответ

1 голос
/ 06 февраля 2020

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

Таким образом, чтобы упростить вещи, компилятор просто предполагал, что если вы вызываете функцию, эта функция будет существовать и принимать типы аргументов, которые вы используете при вызове и которые возвращают int. Это «неявная декларация». Простой вызов функции неявно объявляет ее. Эта функция существует и по сей день.

Так что это не так много, что компилятор каким-то образом видит эти защищенные / частные функции, но просто и вслепую предполагает, что они существуют, и, к удивлению, когда вы позже связываете объектные файлы вместе, они делают .

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

...