Visão Geral do Projeto
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 44 de 61.
Desafio
FácilVamos lançar as bases para o projeto Shape Drawer criando a struct base Shape — uma interface que define o que qualquer forma pode fazer através de ponteiros de função.
Você criará dois arquivos para configurar este sistema polimórfico:
shape.h: Defina a interface principal aqui. Primeiro, crie uma declaração antecipada (forward declaration) para a structShape. Em seguida, defina dois tipos de ponteiros de função:DrawFunc— recebe um parâmetroconst Shape*e não retorna nadaAreaFunc— recebe um parâmetroconst Shape*e retorna umdouble
Shapecontendo dois ponteiros de função:draw(do tipoDrawFunc) earea(do tipoAreaFunc). Esta struct atua puramente como uma interface — ela não contém dados específicos da forma, apenas comportamento.main.c: Demonstre que sua interface funciona criando uma forma de teste simples. Implemente duas funções:test_draw— imprimeDrawing test shapetest_area— retorna42.0
Shape, conecte-a a essas funções de teste e, em seguida, chame ambas através da interface. Imprima o resultado da área com uma casa decimal.
Sua saída deve demonstrar que os ponteiros de função funcionam corretamente:
Drawing test shape
Area: 42.0Por que a declaração antecipada? Você pode se perguntar por que typedef struct Shape Shape; aparece antes da struct ser totalmente definida. Isso é necessário porque DrawFunc e AreaFunc referenciam const Shape* em seus tipos de parâmetros — mas, nesse ponto do arquivo, o compilador ainda não viu a definição completa da struct. A declaração antecipada diz ao compilador: "uma struct chamada Shape existe", o que é suficiente para usar um ponteiro para ela. A definição completa segue depois. Esse padrão é comum em C sempre que uma struct precisa referenciar a si mesma (diretamente ou através de ponteiros de função).
A ideia central aqui é que Shape não sabe nada sobre círculos ou retângulos — ela apenas sabe que qualquer forma deve ser capaz de desenhar (draw) a si mesma e calcular sua área (area). Nas próximas lições, você criará formas concretas que incorporam esta struct base e fornecem suas próprias implementações. Lembre-se de usar guards de inclusão (include guards) em seu arquivo de cabeçalho.
Experimente você mesmo
#include <stdio.h>
#include "shape.h"
// TODO: Implementar a função test_draw
// - Recebe um parâmetro const Shape*
// - Imprime "Drawing test shape"
void test_draw(const Shape* shape) {
// TODO: Imprimir a mensagem solicitada
}
// TODO: Implementar a função test_area
// - Recebe um parâmetro const Shape*
// - Retorna 42.0
double test_area(const Shape* shape) {
// TODO: Retornar o valor de área de teste
}
int main() {
// TODO: Criar uma instância de Shape
// TODO: Vincular a forma às funções test_draw e test_area
// TODO: Chamar draw através da interface
// TODO: Chamar area através da interface e imprimir com uma casa decimal
// Formato: "Area: %.1f\n"
return 0;
}
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