💻 Exemplos: Capítulo 11: Herança, Polimorfismo Dinâmico e a Mecânica da VTable
💻 Exemplos: Capítulo 11: Herança, Polimorfismo Dinâmico e a Mecânica da VTable
Especialização em Sistemas com C++ • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Apresentar o polimorfismo dinâmico orientado a objetos em C++: criação de classes base puramente abstratas (interfaces), aplicação dos especificadores override e final, a necessidade crítica do destrutor virtual em hierarquias polimórficas para evitar undefined behavior e a inspeção prática do custo de indireção da tabela de métodos virtuais (vptr / VTable).
1. Código Fonte Completo (main.cpp)
/**
* @file main.cpp
* @brief Polimorfismo dinâmico, destrutores virtuais e custo da VTable em C++20.
*/
#include <iostream>
#include <memory>
#include <vector>
#include <string>
// 1. Classe Base Puramente Abstrata (Interface)
class CanalComunicacao {
public:
virtual ~CanalComunicacao() {
std::cout << "[VTable] Destrutor virtual do CanalComunicacao invocado." << '\n';
}
// Métodos virtuais puros (= 0)
virtual void conectar() = 0;
virtual void enviar_payload(const std::string& dados) = 0;
virtual void desconectar() = 0;
};
// 2. Implementação Concreta de Canal TCP
class CanalTCP final : public CanalComunicacao {
private:
std::string m_endereco_ip;
int m_porta;
public:
CanalTCP(std::string ip, int porta)
: m_endereco_ip(std::move(ip)), m_porta(porta) {}
~CanalTCP() override {
std::cout << "[TCP] Conexao encerrada no socket TCP " << m_endereco_ip << ":" << m_porta << '\n';
}
void conectar() override {
std::cout << "[TCP] Handshake TCP SYN-ACK estabelecido com " << m_endereco_ip << ":" << m_porta << '\n';
}
void enviar_payload(const std::string& dados) override {
std::cout << "[TCP] Transmitindo " << dados.size() << " bytes via socket TCP." << '\n';
}
void desconectar() override {
std::cout << "[TCP] Enviando pacote FIN/ACK..." << '\n';
}
};
// 3. Implementação Concreta de Canal Memória Compartilhada (IPC)
class CanalIPC final : public CanalComunicacao {
private:
std::string m_shm_id;
public:
explicit CanalIPC(std::string shm_id) : m_shm_id(std::move(shm_id)) {}
~CanalIPC() override {
std::cout << "[IPC] Memoria compartilhada desanexada: " << m_shm_id << '\n';
}
void conectar() override {
std::cout << "[IPC] Mapeando regiao de memoria SHM: " << m_shm_id << '\n';
}
void enviar_payload(const std::string& dados) override {
std::cout << "[IPC] memcpy direto de " << dados.size() << " bytes para SHM ring buffer." << '\n';
}
void desconectar() override {
std::cout << "[IPC] Desmapeando ponteiro SHM." << '\n';
}
};
int main() {
std::cout << "=== CAPÍTULO 11: POLIMORFISMO E VTABLE EM C++20 ===" << '\n';
// 4. Demonstração de Custo de Indireção da VTable: O ponteiro oculto vptr
std::cout << "Tamanho de CanalComunicacao com VTable (sizeof): " << sizeof(CanalComunicacao)
<< " bytes (contem o ponteiro virtual oculto __vptr)" << '\n';
// 5. Coleção Heterogênea Polimórfica com std::unique_ptr
std::vector<std::unique_ptr<CanalComunicacao>> canais;
canais.emplace_back(std::make_unique<CanalTCP>("192.168.1.100", 8080));
canais.emplace_back(std::make_unique<CanalIPC>("/dev/shm/telemetry_queue"));
std::cout << "\n--- Despacho Polimorfico via VTable (Dynamic Dispatch) ---" << '\n';
for (const auto& canal : canais) {
canal->conectar();
canal->enviar_payload("TELEMETRY_PACKET_#001");
canal->desconectar();
std::cout << "------------------------------------------" << '\n';
}
// Ao esvaziar o vetor, os destrutores derivados e bases são invocados na ordem correta
std::cout << "Limpando colecao de canais (destruicao polimorfica segura)..." << '\n';
canais.clear();
return 0;
}
2. Instruções de Compilação e Execução
# Compilação com GCC / Clang
g++ -std=c++20 -Wall -Wextra -O2 main.cpp -o app_polimorfismo
./app_polimorfismo
# Compilação com MSVC
cl /std:c++20 /EHsc /W4 /O2 main.cpp /Fe:app_polimorfismo.exe
.\app_polimorfismo.exe
3. Saída Esperada no Terminal
=== CAPÍTULO 11: POLIMORFISMO E VTABLE EM C++20 ===
Tamanho de CanalComunicacao com VTable (sizeof): 8 bytes (contem o ponteiro virtual oculto __vptr)
--- Despacho Polimorfico via VTable (Dynamic Dispatch) ---
[TCP] Handshake TCP SYN-ACK estabelecido com 192.168.1.100:8080
[TCP] Transmitindo 21 bytes via socket TCP.
[TCP] Enviando pacote FIN/ACK...
------------------------------------------
[IPC] Mapeando regiao de memoria SHM: /dev/shm/telemetry_queue
[IPC] memcpy direto de 21 bytes para SHM ring buffer.
[IPC] Desmapeando ponteiro SHM.
------------------------------------------
Limpando colecao de canais (destruicao polimorfica segura)...
[TCP] Conexao encerrada no socket TCP 192.168.1.100:8080
[VTable] Destrutor virtual do CanalComunicacao invocado.
[IPC] Memoria compartilhada desanexada: /dev/shm/telemetry_queue
[VTable] Destrutor virtual do CanalComunicacao invocado.