Menu
Coddy logo textTech

Доступ к элементам родителя

Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 30 из 61.

Теперь, когда мы понимаем встраивание структур и правило первого участника, сосредоточимся на практической стороне: как читать и изменять данные встроенного parent из функции.

Когда функция получает структуру Child (или указатель на неё), для доступа к членам parent требуется перейти через встроенную структуру. Синтаксис зависит от того, работаете ли вы со значением или указателем.

typedef struct {
    int id;
    int score;
} Parent;

typedef struct {
    Parent parent;
    char grade;
} Child;

Имея указатель на Child, используй оператор стрелки, чтобы обратиться к parent, затем точку для доступа к его членам:

void update_score(Child* c, int new_score) {
    c->parent.score = new_score;  // Стрелка, затем точка
}

void print_info(Child* c) {
    printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}

С значением (переданным копированием) используйте точки повсюду:

void show_id(Child c) {
    printf("ID: %d\n", c.parent.id);  // Точка затем точка
}

Этот шаблон последовательного доступа, child->parent.member или child.parent.member, позволяет взаимодействовать с унаследованными данными в модели композиции C. Он немного более многословен, чем настоящее наследование, но явно и чётко показывает отношение между типами.

challenge icon

Задание

Легко

Давайте создадим систему оценивания студентов, демонстрирующую, как получать доступ к данным внутри встроенной структуры и изменять их. Вы создадите иерархию, в которой Student содержит встроенную Person, а затем напишете функции, работающие с данными parent через дочернюю структуру.

Вы организуете код в трёх файлах:

  • student.h: Определите иерархию структур с защитой от повторного включения. Создайте структуру Person с полем name (массивом символов из 50 символов) и полем age (целым числом). Затем определите структуру Student, которая встраивает Person как своего first member и добавляет поле grade (целое число, представляющее оценку). Объявите две функции: set_person_age, которая принимает Student* и новое значение age, и print_student, которая принимает Student* и отображает all information.
  • student.c: Реализуйте обе функции. Ваша функция set_person_age должна изменять age внутри встроенной структуры Person. Здесь вы попрактикуетесь в синтаксисе arrow-then-dot (s->person.age). Ваша функция print_student должна получать доступ ко всем полям встроенного person и самого student и отображать их.
  • main.c: Создайте переменную Student и инициализируйте все её поля. Затем используйте set_person_age, чтобы обновить age встроенного person, и вызовите print_student, чтобы отобразить результат.

Вы получите четыре входных значения: name студента (строку), его initial age (целое число), его grade (целое число) и new age (целое число для обновления с помощью вашей функции).

В основном файле создайте student с начальными значениями, затем вызовите set_person_age, чтобы изменить age на новое значение, и наконец вызовите print_student, чтобы отобразить обновлённую information.

Ваш вывод должен выглядеть так:

Name: Emma
Age: 21
Grade: 85

Здесь Emma — это имя, 21 — обновлённый age (а не initial age), а 85 — grade. Главный вывод здесь — научиться перемещаться по встроенной структуре, чтобы как читать, так и записывать members parent.

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

#include <stdio.h>
#include <string.h>
#include "student.h"

int main() {
    char name[50];
    int initial_age, grade, new_age;
    
    // Считать входные данные
    fgets(name, 50, stdin);
    name[strcspn(name, "\n")] = '\0';  // Удалить символ новой строки
    scanf("%d", &initial_age);
    scanf("%d", &grade);
    scanf("%d", &new_age);
    
    // TODO: Создать переменную Student
    
    // TODO: Инициализировать все поля студента
    // - Скопировать name в имя вложенного person с помощью strcpy
    // - Установить возраст вложенного person равным initial_age
    // - Установить grade студента
    
    // TODO: Вызвать set_person_age, чтобы обновить возраст на new_age
    
    // TODO: Вызвать print_student для вывода результата
    
    return 0;
}
quiz iconПроверьте себя

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

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C