Menu
Coddy logo textTech

Обзор проекта

Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 44 из 61.

challenge icon

Задание

Легко

Давайте заложим основу для проекта Shape Drawer, создав базовую структуру Shape — интерфейс, который определяет, что может делать любая фигура, с помощью указателей на функции.

Вы создадите два файла для настройки этой полиморфной системы:

  • shape.h: Определите здесь основной интерфейс. Сначала создайте опережающее объявление (forward declaration) для структуры Shape. Затем определите два типа указателей на функции:
    • DrawFunc — принимает параметр const Shape* и ничего не возвращает
    • AreaFunc — принимает параметр const Shape* и возвращает double
    Наконец, определите саму структуру Shape, содержащую два указателя на функции: draw (типа DrawFunc) и area (типа AreaFunc). Эта структура действует исключительно как интерфейс — она не содержит данных, специфичных для конкретной фигуры, только поведение.
  • main.c: Продемонстрируйте работу вашего интерфейса, создав простую тестовую фигуру. Реализуйте две функции:
    • test_draw — выводит Drawing test shape
    • test_area — возвращает 42.0
    Создайте экземпляр Shape, привяжите его к этим тестовым функциям, а затем вызовите обе через интерфейс. Выведите результат площади с одним десятичным знаком.

Ваш вывод должен продемонстрировать, что указатели на функции работают правильно:

Drawing test shape
Area: 42.0

Зачем нужно опережающее объявление? Вы можете задаться вопросом, почему typedef struct Shape Shape; появляется до того, как структура полностью определена. Это необходимо, потому что DrawFunc и AreaFunc ссылаются на const Shape* в своих типах параметров — но в этот момент в файле компилятор еще не видел полного определения структуры. Опережающее объявление говорит компилятору: "структура с именем Shape существует", чего достаточно для использования указателя на нее. Полное определение следует позже. Этот паттерн часто встречается в C, когда структуре нужно ссылаться на саму себя (напрямую или через указатели на функции).

Ключевая идея здесь заключается в том, что Shape ничего не знает о кругах или прямоугольниках — она знает только то, что любая фигура должна уметь отрисовывать (draw) себя и вычислять свою площадь (area). В следующих уроках вы создадите конкретные фигуры, которые будут включать эту базовую структуру и предоставлять свои собственные реализации. Не забудьте использовать include guards в заголовочном файле.

Попробуйте сами

#include <stdio.h>
#include "shape.h"

// TODO: Реализуйте функцию test_draw
// - Принимает параметр const Shape*
// - Выводит "Drawing test shape"
void test_draw(const Shape* shape) {
    // TODO: Выведите требуемое сообщение
}

// TODO: Реализуйте функцию test_area
// - Принимает параметр const Shape*
// - Возвращает 42.0
double test_area(const Shape* shape) {
    // TODO: Верните тестовое значение площади
}

int main() {
    // TODO: Создайте экземпляр Shape
    
    // TODO: Привяжите функции test_draw и test_area к фигуре
    
    // TODO: Вызовите draw через интерфейс
    
    // TODO: Вызовите area через интерфейс и выведите результат с одним знаком после запятой
    // Формат: "Area: %.1f\n"
    
    return 0;
}

Все уроки раздела Object Oriented Programming