Наследование в C: как скрыть атрибуты «суперкласса» для класса, расширяющего его - PullRequest
1 голос
/ 12 февраля 2020

Как опыт обучения, я пытаюсь добиться простого наследования классов в C, среди других OOP функций.

До сих пор я был в состоянии правильно скрывать "частные" функции и атрибуты класса из внешнего контекста.

Давайте рассмотрим Point как простой пример класса. Он состоит из трех модулей:

publi c .h

#ifndef POINT_PUBLIC_H_
#define POINT_PUBLIC_H_

typedef struct Point Point;

Point* newPoint(const int x, const int y);

int getX(const Point* self);

int getY(const Point* self);

void setX(Point* self, const int x);

void setY(Point* self, const int y);

void printPoint(const Point* self);

#endif

Это в основном интерфейс Publi c для Point и он также определяет тип Point, ссылающийся на Структура, объявленная в другом модуле, скрывающая его атрибуты.

protected.h

#ifndef POINT_PROTECTED_H_
#define POINT_PROTECTED_H_

struct Point {

    int x;
    int y;
};

#endif

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

И еще есть реализация. c, которая включает в себя как publi c .h, так и protected.h и содержит фактический код publi c, защищенных и приватных функций.

Это прекрасно работает, но что, если я хотел определить класс Circle, который расширяет Point?

Я предполагал что-то вроде этого:

#ifndef CIRCLE_PROTECTED_H_
#define CIRCLE_PROTECTED_H_

#include "../Point/protected.h"

struct Circle {

    Point parent;
    int radius;
};

#endif

Поскольку ожидаемые функции Point 1010 * публикуются указатель на Point, и поскольку первый атрибут структуры Circle является Point (не указатель на него), для данного объекта Circle* c становится возможным сделать что-то вроде getX((Point*) c);. Хотя это работает нормально, меня не радует то, что я могу напрямую обращаться к атрибутам объекта Point (включая тот, что в структуре Circle, конечно) в модулях Circle. Перемещение определения структуры в модуль реализации сделало бы его атрибуты полностью закрытыми, но тогда я не смог бы напрямую определить объект Point, чтобы настроить механизм наследования. Есть ли способ заставить наследование работать при сохранении конфиденциальности расширяемого класса?

1 Ответ

0 голосов
/ 12 февраля 2020

Благодаря тому, что @RobertS поддерживает Monica Cellio, я некоторое время просматривал нить, которую вы связали, и это действительно дало мне идею.

Я пытался разделить структуру на две части, защищенную часть, которая предназначен для того, чтобы быть видимым посредством наследующих классов и закрытой части, которая полностью невидима вне реализации. c module.

Вот что я сделал: в реализации. c Я определил новую структуру который содержит все личные атрибуты:

struct hiddenPoint {

    int x;
    int y;
};

В protected.h я определил тип, ссылающийся на эту новую структуру, и поместил указатель на него в фактической структуре Point

typedef struct hiddenPoint hiddenPoint;

struct Point {

    int aCircleCanSeeThis;
    hiddenPoint* hidden;
};

Поскольку скрытый является непрозрачным указателем, даже когда структура Point является видимой, некоторые ее атрибуты все еще могут быть недоступны. Эта структура, конечно же, может содержать защищенные атрибуты, как показано.

Это моя структура Круга:

struct Circle {

    Point parent;
    hiddenCircle* hidden;
};

Кажется, она работает. Конечно, это немного усложняет ситуацию (теперь это p-> hidden-> x, а не просто p-> x), но делает то, что я искал. Не знаю, если это хорошее решение, может быть, дайте мне знать! Кроме того, если есть другие подходы, я все же хотел бы услышать о них:)

...