Menu
Coddy logo textTech

Паттерн «Конструктор»

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

В таких языках, как Java или C++, вы создаете объекты с помощью конструкторов — специальных функций, которые автоматически выделяют память и инициализируют поля. В языке C такой возможности нет, но мы можем имитировать ее с помощью простого паттерна: функции create_.

Функция-конструктор в C обычно выполняет три действия: выделяет память с помощью malloc, инициализирует все поля соответствующими значениями и возвращает указатель на новый объект:

typedef struct {
    char *name;
    int age;
} Person;

Person *create_person(const char *name, int age) {
    Person *p = malloc(sizeof(Person));
    p->name = malloc(strlen(name) + 1);
    strcpy(p->name, name);
    p->age = age;
    return p;
}

Функция возвращает указатель, так как объект располагается в куче, а не в стеке. Это означает, что он продолжает существовать после возврата из функции и его можно свободно передавать. Вызывающий код использует его так:

Person *alice = create_person("Alice", 30);
printf("%s is %d years old\n", alice->name, alice->age);

Обратите внимание, как конструктор берет на себя все сложные детали — выделение памяти под структуру, выделение места для строки и копирование данных. Вызывающая сторона просто предоставляет начальные значения и получает готовый к использованию объект. Это инкапсулирует логику создания в одном месте, делая ваш код чище и менее подверженным ошибкам.

challenge icon

Задание

Легко

Давайте создадим модуль Book, который использует паттерн конструктора для создания объектов книг в куче. Вы попрактикуетесь в написании функции create_, которая берет на себя все задачи по выделению памяти и инициализации, возвращая готовый к использованию указатель.

Вы создадите три файла:

  • book.h: Объявите структуру Book с двумя полями: char *title (указатель на динамически выделенную строку) и int pages. Также объявите функцию-конструктор create_book, которая принимает строку заголовка и количество страниц, а затем возвращает указатель на вновь созданную структуру Book. Используйте include guards с символом BOOK_H.
  • book.c: Реализуйте функцию create_book. Ваш конструктор должен выделить память для самой структуры Book, затем выделить отдельную память для строки заголовка (не забудьте учесть нулевой терминатор), скопировать заголовок в новую память, установить поле pages и вернуть указатель на новую Book.
  • main.c: Используйте ваш конструктор для создания книги и вывода информации о ней.

Вы получите два входных значения: название книги (строка) и количество страниц (целое число).

В вашем основном файле используйте create_book для создания новой книги с предоставленными значениями, а затем выведите информацию о ней в следующем формате:

Title: {title}
Pages: {pages}

Например, при входных данных The C Programming Language и 272, вывод будет следующим:

Title: The C Programming Language
Pages: 272

Помните, что ваш конструктор инкапсулирует всю логику создания — вызывающая сторона просто предоставляет начальные значения и получает полностью инициализированный объект, готовый к использованию.

Шпаргалка

Функция-конструктор в C имитирует создание объекта путем выделения памяти и инициализации полей. Обычно она следует шаблону именования create_.

Функция-конструктор делает три вещи:

  • Выделяет память с помощью malloc
  • Инициализирует все поля соответствующими значениями
  • Возвращает указатель на новый объект

Пример шаблона конструктора:

typedef struct {
    char *name;
    int age;
} Person;

Person *create_person(const char *name, int age) {
    Person *p = malloc(sizeof(Person));
    p->name = malloc(strlen(name) + 1);
    strcpy(p->name, name);
    p->age = age;
    return p;
}

Использование конструктора:

Person *alice = create_person("Alice", 30);
printf("%s is %d years old\n", alice->name, alice->age);

Функция возвращает указатель, потому что объект находится в куче и сохраняется после завершения работы функции. Это инкапсулирует логику создания в одном месте, делая код чище и менее подверженным ошибкам.

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

#include <stdio.h>
#include <stdlib.h>
#include "book.h"

int main() {
    char title[256];
    int pages;
    
    // Чтение входных данных
    fgets(title, sizeof(title), stdin);
    // Удаление символа новой строки, если он есть
    for (int i = 0; title[i]; i++) {
        if (title[i] == '\n') {
            title[i] = '\0';
            break;
        }
    }
    scanf("%d", &pages);
    
    // TODO: Используйте create_book для создания новой книги с предоставленными значениями
    
    // TODO: Выведите информацию о книге в требуемом формате:
    // Название: {title}
    // Страницы: {pages}
    
    // TODO: Не забудьте освободить выделенную память по завершении
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

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