💻 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.