Доступ к элементам родителя
Часть раздела Объектно-ориентированное программирование путешествия по 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. Он немного более многословен, чем настоящее наследование, но явно и чётко показывает отношение между типами.
Задание
ЛегкоДавайте создадим систему оценивания студентов, демонстрирующую, как получать доступ к данным внутри встроенной структуры и изменять их. Вы создадите иерархию, в которой 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;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация кругаРеализация прямоугольникаПолиморфное использованиеКонтейнер фигурПотренируйтесь самостоятельно: Онлайн-компилятор C