Acessando Membros Pai
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 30 de 61.
Agora que entendemos a incorporação de structs e a regra do primeiro membro, vamos focar no lado prático: como ler e modificar os dados do pai incorporado de dentro de uma função.
Quando uma função recebe uma struct Child (ou um ponteiro para uma), acessar os membros do pai requer navegar através da struct incorporada. A sintaxe depende se você está trabalhando com um valor ou um ponteiro.
typedef struct {
int id;
int score;
} Parent;
typedef struct {
Parent parent;
char grade;
} Child;Com um ponteiro para Child, use o operador de seta para alcançar o pai e, em seguida, o ponto para acessar seus membros:
void update_score(Child* c, int new_score) {
c->parent.score = new_score; // Seta e depois ponto
}
void print_info(Child* c) {
printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}Com um valor (passado por cópia), use pontos em tudo:
void show_id(Child c) {
printf("ID: %d\n", c.parent.id); // Ponto depois ponto
}Este padrão de acesso encadeado — child->parent.member ou child.parent.member — é como você interage com dados herdados no modelo de composição do C. É um pouco mais verboso do que a herança verdadeira, mas é explícito e claro sobre a relação entre os tipos.
Desafio
FácilVamos construir um sistema de notas de alunos que demonstra como acessar e modificar dados dentro de uma struct incorporada (embedded struct). Você criará uma hierarquia onde um Student contém uma Person incorporada, e então escreverá funções que trabalham com os dados do pai através do filho.
Você organizará seu código em três arquivos:
student.h: Defina sua hierarquia de structs com guards de inclusão. Crie uma structPersoncomname(um array de caracteres de 50 caracteres) eage(um inteiro). Em seguida, defina uma structStudentque incorporaPersoncomo seu primeiro membro e adiciona um campograde(um inteiro representando sua nota). Declare duas funções:set_person_ageque recebe umStudent*e um novo valor de idade, eprint_studentque recebe umStudent*e exibe todas as informações.student.c: Implemente ambas as funções. Sua funçãoset_person_agedeve modificar a idade dentro da structPersonincorporada — é aqui que você praticará a sintaxe de seta e depois ponto (s->person.age). Sua funçãoprint_studentdeve acessar e exibir todos os campos tanto da pessoa incorporada quanto do próprio aluno.main.c: Crie uma variávelStudente inicialize todos os seus campos. Em seguida, useset_person_agepara atualizar a idade da pessoa incorporada e chameprint_studentpara exibir o resultado.
Você receberá quatro entradas: o name do aluno (uma string), sua initial age (um inteiro), sua grade (um inteiro) e uma new age (um inteiro para atualizar via sua função).
Em seu arquivo principal, crie o aluno com os valores iniciais, chame set_person_age para alterar a idade para o novo valor e, finalmente, chame print_student para exibir as informações atualizadas.
Sua saída deve ser parecida com esta:
Name: Emma
Age: 21
Grade: 85Onde Emma é o nome, 21 é a idade atualizada (não a idade inicial) e 85 é a nota. O aprendizado principal aqui é navegar através da struct incorporada para ler e escrever nos membros do pai.
Folha de consulta
Para acessar membros de uma struct pai incorporada a partir de uma função, use a sintaxe de acesso encadeado que depende se você está trabalhando com um ponteiro ou um valor.
Com um ponteiro para a struct filha, use o operador de seta para alcançar o pai incorporado e, em seguida, a notação de ponto para acessar seus membros:
void update_score(Child* c, int new_score) {
c->parent.score = new_score; // Seta depois ponto
}
void print_info(Child* c) {
printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}Com um valor (passado por cópia), use a notação de ponto em tudo:
void show_id(Child c) {
printf("ID: %d\n", c.parent.id); // Ponto depois ponto
}Este padrão — child->parent.member ou child.parent.member — fornece acesso explícito aos dados herdados no modelo de composição do C.
Experimente você mesmo
#include <stdio.h>
#include <string.h>
#include "student.h"
int main() {
char name[50];
int initial_age, grade, new_age;
// Ler as entradas
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = '\0'; // Remover a quebra de linha
scanf("%d", &initial_age);
scanf("%d", &grade);
scanf("%d", &new_age);
// TODO: Criar uma variável Student
// TODO: Inicializar todos os campos do estudante
// - Copiar name para o nome da pessoa incorporada usando strcpy
// - Definir a idade da pessoa incorporada como initial_age
// - Definir a nota (grade) do estudante
// TODO: Chamar set_person_age para atualizar a idade para new_age
// TODO: Chamar print_student para exibir o resultado
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Fundamentos da Programação Modular
Arquivos de CabeçalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do Círculo