Ponteiros para funções em structs
Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 38 de 61.
Até agora, usamos ponteiros para funções como variáveis independentes ou os passamos como argumentos. O próximo passo rumo ao polimorfismo é inserir um ponteiro para função diretamente em uma struct, dando à struct seu próprio comportamento.
Quando uma struct contém um ponteiro para função, cada instância pode armazenar uma função diferente. Isso significa que dois objetos do mesmo tipo podem se comportar de maneiras diferentes quando você chama o ponteiro para função deles:
typedef void (*PrintFunc)(const char*);
typedef struct {
const char* name;
PrintFunc print; // Ponteiro para função como membro
} Printer;A estrutura Printer agora tem dois membros: dados (name) e comportamento (print). Para usá-la, você atribui uma função ao ponteiro durante a inicialização:
void loud_print(const char* msg) {
printf("!!! %s !!!\n", msg);
}
int main() {
Printer p;
p.name = "Alert";
p.print = loud_print;
p.print("Hello"); // Saída: !!! Hello !!!
return 0;
}Observe como chamamos a função por meio da struct: p.print("Hello"). Isso se parece muito com chamar um método em um objeto em outras linguagens. A struct contém tanto seus dados quanto a função que opera sobre ela.
Esse padrão é a base do polimorfismo em C: diferentes instâncias podem ter funções diferentes atribuídas, produzindo comportamentos diferentes a partir do mesmo tipo de struct.
Desafio
FácilVamos criar um sistema Notifier que demonstra como structs podem carregar seu próprio comportamento por meio de ponteiros de função.
Você criará dois arquivos para organizar seu código:
notifier.h: Defina um tipo de ponteiro de função chamadoNotifyFuncque recebe um parâmetroconst char*e não retorna nada. Em seguida, defina uma structNotifierque contenha umname(umconst char*) e um ponteiro de funçãonotifydo tipoNotifyFunc.main.c: Inclua seu cabeçalho e implemente duas funções de notificação:alert_notify: exibe a mensagem no formato:[ALERT] messageinfo_notify: exibe a mensagem no formato:[INFO] message
Notifier, associe a função apropriada com base na entrada e chame a notificação por meio do ponteiro de função da struct.
Seu programa receberá duas entradas: um tipo de notificação (1 para alerta, 2 para informação) e uma mensagem a ser exibida.
Com base no tipo, atribua a função correspondente ao membro notify do seu notifier e, em seguida, chame-a por meio da struct para exibir a mensagem.
Exemplo de saída quando o tipo é 1 e a mensagem é "System starting":
[ALERT] System startingExemplo de saída quando o tipo é 2 e a mensagem é "All systems normal":
[INFO] All systems normalLembre-se de usar include guards no arquivo de cabeçalho e chamar a função por meio do membro da struct: n.notify(message)
Experimente você mesmo
#include <stdio.h>
#include "notifier.h"
// TODO: Implemente a função alert_notify
// Deve imprimir: [ALERT] message
// TODO: Implemente a função info_notify
// Deve imprimir: [INFO] message
int main() {
int type;
char message[256];
// Leia a entrada
scanf("%d", &type);
getchar(); // consuma o caractere de nova linha
fgets(message, sizeof(message), stdin);
// Remova o caractere de nova linha no final de message, se houver
int len = 0;
while (message[len] != '\0') len++;
if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
// TODO: Crie uma instância de Notifier
// TODO: Com base em type (1 para alert, 2 para info),
// atribua a função apropriada ao membro notify de notifier
// TODO: Chame a notificação por meio do ponteiro para função da struct
// Use: n.notify(message)
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 Programação Orientada a Objetos
1Fundamentos da Programação Modular
Arquivos de cabeçalhoProteções de inclusãoArquivos-fonteFunções estáticasRevisão: calculadora modular4Encapsulamento
Conceito de ponteiros opacosDefinindo structs opacasGetters e settersValidação em settersRevisão: caixa secreta2Objetos e métodos
Structs como objetosO ponteiro 'Self'Correção de constPonteiro vs. valorMétodos auxiliaresRevisão: Gerenciador de pontos5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta8Polimorfismo
Ponteiros para funções em structsSimulando métodosO conceito de interfaceImplementando interfacesIteração polimórficaRevisão: Greeter3Ciclo de vida do objeto
Padrão de construtorPadrão de destrutorInicialização da pilhaCópia profundaRevisão: wrapper de String6Herança por composição
Incorporação de structRegra do primeiro membroAcessando membros do tipo paiUpcastingRevisão: hierarquia de formas9Projeto: Desenhador de Formas
Visão geral do projetoImplementação do círculoImplementação do retânguloUso polimórficoContêiner de formasPratique por conta própria: Compilador de C online