Incorporação de Structs
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 28 de 61.
Em linguagens orientadas a objetos como C++ ou Java, a herança permite que uma classe adquira propriedades de uma classe pai. C não possui herança nativa, mas podemos simulá-la usando uma técnica chamada composição — colocando uma struct dentro de outra.
A ideia é simples: se um Child precisa de todas as propriedades de um Parent, incorporamos a struct Parent como um membro de Child.
typedef struct {
int id;
char name[50];
} Parent;
typedef struct {
Parent parent; // Estrutura incorporada
int grade;
} Child;Aqui, Child contém tudo o que Parent tem, além de seu próprio campo grade. Isso é composição — o filho "tem um" pai em vez de "ser um" pai, mas o efeito é semelhante à herança.
Para acessar os membros do pai através de uma instância filha, você usa o operador ponto duas vezes:
Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;Este padrão forma a base para a construção de hierarquias de tipos em C. Ao incorporar uma struct base como o primeiro membro, desbloqueamos técnicas poderosas que exploraremos nas próximas lições.
Desafio
FácilVamos construir um sistema simples de gerenciamento de funcionários que demonstra a incorporação de structs — a base da herança em C.
Você criará uma hierarquia onde um Employee contém um Person. Isso reflete como a herança funciona: um funcionário "é uma" pessoa com informações adicionais relacionadas ao trabalho. Ao incorporar a struct Person dentro de Employee, você obtém todas as propriedades da pessoa mais os campos específicos do funcionário.
Você organizará seu código em três arquivos:
types.h: Defina ambas as structs aqui com guards de inclusão. Primeiro, crie uma structPersoncom dois campos:name(um array de caracteres de 50 caracteres) eage(um inteiro). Em seguida, defina uma structEmployeeque incorporaPersoncomo seu primeiro membro e adiciona um campoemployee_id(um inteiro).types.c: Implemente uma função chamadaprint_employeeque recebe um ponteiro para umEmployeee imprime suas informações. Acesse os dados da pessoa incorporada usando a sintaxe encadeada de ponto/seta que você aprendeu.main.c: Crie uma variávelEmployee, preencha todos os seus campos (incluindo o nome e a idade da pessoa incorporada) e use sua função de impressão para exibir as informações.
Você receberá três entradas: o nome do funcionário (uma string), sua idade (um inteiro) e seu ID de funcionário (um inteiro).
Sua função print_employee deve exibir as informações do funcionário neste formato:
Employee: Alice
Age: 28
ID: 1001Onde Alice é o nome, 28 é a idade e 1001 é o ID do funcionário das suas entradas.
Lembre-se de acessar os membros da struct incorporada através do membro pai — por exemplo, para chegar ao nome, você navegará pelo membro person primeiro.
Folha de consulta
C não possui herança nativa, mas você pode simulá-la usando composição — incorporando uma struct dentro de outra.
Para criar uma relação pai-filho, incorpore a struct pai como um membro da struct filha:
typedef struct {
int id;
char name[50];
} Parent;
typedef struct {
Parent parent; // Embedded struct
int grade;
} Child;A struct filha contém todas as propriedades da pai, além de seus próprios campos adicionais. Isso representa uma relação do tipo "tem um" (has a).
Para acessar os membros da struct incorporada, use o operador de ponto duas vezes:
Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;Ao trabalhar com ponteiros, use o operador de seta para acessar os membros da struct incorporada:
Child *ptr = &c;
ptr->parent.id = 101;
ptr->grade = 5;Incorporar a struct base como o primeiro membro é um padrão comum que permite técnicas avançadas para construir hierarquias de tipos em C.
Experimente você mesmo
#include <stdio.h>
#include <string.h>
#include "types.h"
int main() {
// Ler entrada
char name[50];
int age;
int employee_id;
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = '\0'; // Remover nova linha
scanf("%d", &age);
scanf("%d", &employee_id);
// TODO: Criar uma variável Employee
// TODO: Preencher o nome e a idade da pessoa incorporada
// Dica: Use strcpy para o nome, acesse com employee.person.name
// TODO: Definir o employee_id
// TODO: Chamar print_employee com um ponteiro para o seu employee
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