He hecho esto innumerables veces: es un escenario muy común. Hay una serie de cosas que hago casi siempre.
No se preocupe demasiado por hacerlo la cosa más eficiente disponible.
Si terminamos pasando mucho tiempo empaquetando y desempacando paquetes, entonces siempre podemos cambiarlo para que sea más eficiente. Aunque todavía no he encontrado un caso en el que haya tenido que hacerlo, ¡no he estado implementando enrutadores de red!
Si bien el uso de structs/unions es el enfoque más eficiente en términos de tiempo de ejecución, presenta una serie de complicaciones: convencer al compilador de empaquetar las estructuras/uniones para que coincidan con la estructura de octetos de los paquetes que necesita; problemas de alineación y endianness, y una falta de seguridad ya que no hay o hay poca oportunidad de hacer verificaciones de cordura en las compilaciones de depuración.
a menudo terminan con una arquitectura que incluye los siguientes tipos de cosas: clase base
- un paquete. Todos los campos de datos comunes son accesibles (pero no modificables).Si los datos no se almacenan en un formato empaquetado, entonces hay una función virtual que producirá un paquete empaquetado.
- Varias clases de presentación para tipos de paquetes específicos, derivadas del tipo de paquete común. Si estamos utilizando una función de embalaje, entonces cada clase de presentación debe implementarlo.
- Cualquier cosa que pueda inferirse del tipo específico de la clase de presentación (es decir, un id del tipo de paquete de un campo de datos común), se trata como parte de la inicialización y no puede modificarse.
- Cada clase de presentación se puede construir a partir de un paquete desempaquetado, o fallará elegantemente si los datos del paquete no son válidos para ese tipo. Esto puede ser envuelto en una fábrica por conveniencia.
- Si no tenemos RTTI disponible, podemos obtener "RTTI de un pobre" utilizando el identificador de paquete para determinar qué clase de presentación específica es realmente un objeto.
En todo esto, es posible (incluso si solo para las compilaciones de depuración) verificar que cada campo que se puede modificar se está estableciendo en un valor razonable. Si bien puede parecer mucho trabajo, es muy difícil tener un paquete con formato no válido, el contenido de los paquetes preenvasados puede ser revisado fácilmente mediante un depurador (ya que todo está en las variables normales de formato nativas de la plataforma).
Si tenemos que implementar un esquema de almacenamiento más eficiente, eso también puede ser envuelto en esta abstracción con un pequeño costo de rendimiento adicional.
Estaba seguro de haber visto un duplicado cercano de esto, pero no pude desenterrarlo. Las respuestas en el enlace relacionado no son tan buenas como las que están aquí, pero aún así ... – dmckee