representante ratificacion modelo juridico facultades exceso acto c++ nullable c++11

c++ - ratificacion - exceso de facultades del representante



¿La mejor manera de representar al miembro anulable en C++? (6)

Posible duplicado:
Valores anulables en C ++

¿Cuál es la mejor manera de representar miembros anulables en C ++?

En C #, podemos usar el tipo Nullable<T> . Tal tipo de datos es muy necesario ya que no todo puede tener un valor significativo . Es un tipo de datos tan importante que @Jon Skeet ha dedicado un capítulo completo, abarcó más de 27 páginas, describiendo solo Nullable<T> en su excelente libro C # en profundidad .

Un ejemplo simple puede ser una clase de Person 1 , definida como:

struct Person { std::string Name; DateTime Birth; DateTime Death; //... };

Como una persona siempre tiene fecha de nacimiento, entonces el miembro de Birth de la clase anterior siempre tendrá algún valor significativo . Pero ¿qué hay de la Death ? ¿Qué valor debería tener si la persona está viva? En C #, este miembro se puede declarar como Nullable<DataTime> 2 que se puede asignar con null si la persona está viva.

En C ++, ¿cuál es la mejor manera de resolver esto? Por el momento, solo tengo una solución en mente: declarar al miembro como puntero :

DataTime *Death;

Ahora su valor puede ser nullptr cuando la persona está viva. Pero fuerza el uso de algo new para una persona muerta, ya que va a tener un valor válido. A su vez, implica que no se puede confiar en el código de semántica de copia predeterminado generado por el compilador. El programador tiene que escribir copy-constructor, copy-assignment, destructor siguiendo la regla de tres (C ++ 03), O en C ++ 11, regla de cinco .

Entonces, ¿tenemos alguna solución mejor y más elegante para este problema que solo hacerla puntero ?

1. Otros ejemplos incluyen tablas de bases de datos relacionales, ya que en muchas columnas de DBMS se pueden agregar valores nulos.

2. También hay una forma abreviada de esto. Uno puede escribir DataTime? que es exactamente lo mismo que Nullable<DateTime> .


¡Puedes hacer lo que legiones de programadores hicieron antes que tú! Use un valor específico como "no presente" ... Por ejemplo, he escuchado que "1 de enero de 2000" era bastante común :-) :-) Por razones de interoperabilidad, podría usar "19 de enero de 2038 03:14:07 UTC" :-) :-) (es una broma, si no está claro. Me estoy refiriendo al problema Y2K y al problema Y2038. Estoy mostrando el problema de usar fechas "especiales" como estados ... Cosas como 11 -11-11 y similar)

El valor máximo / mínimo de su DataTime es probablemente más correcto :-) Y todavía está mal, porque está mezclando un "estado" con un "valor". Es mejor que reconstruyas el tipo Nullable en C ++ (al final es bastante fácil: una clase con plantillas con un bool para null / not null y el campo T)


Cada proyecto en el que he trabajado ha tenido algún tipo de clase de Fallible , Maybe o Nullable . (El nombre real tiende a reflejar para qué lo necesitó la aplicación: Fallible como valor de retorno, Nullable para modelar bases de datos, etc.). Más recientemente, Boost ha presentado boost::optional ; Lamentablemente, usan conversiones implícitas en lugar de una función isValid (named), lo que resulta en un código notablemente menos legible (hasta el punto en que lo evitaría, excepto tal vez para implementar mi propio Maybe ).


Crearía un miembro estático que representa un valor nulo, que comparar la dirección de la fecha de fallecimiento con la dirección del objeto estático. Si son iguales, el valor es NULO.


Depende de DateTime , como dice @Tomalak en su respuesta, boost::optional<> es una solución genérica. Sin embargo, si, por ejemplo, su DateTime es un boost::posix_time::ptime , entonces ya hay soporte para valores especiales (por ejemplo, not_a_date_time o pos_infin ); podría usarlos.


Podrías mirar en Boost.Optional :

struct Person { std::string Name; DateTime Birth; boost::optional<DateTime> Death; //... };

  • Tu Death es "no inicializada" al principio.
  • A continuación, puede asignarle un valor con = , como Death = myDateTime .
  • Cuando Death.is_initialized() , puedes usar Death.get() .
  • Death.reset() nuevo con Death.reset() .

Para casos simples como este, sin embargo, generalmente se considera más coherente simplemente elegir su propio valor centinela como, por ejemplo, un DateTime de "0000-00-00 00:00:00".


dado que es poco probable que la muerte sea en cualquier momento antes del nacimiento, podrías ponerla en marcha inicialmente y cambiarla en el evento real. en términos más comunes, probablemente llamaría nacimiento - 1 un valor centinela o un valor de marcador de posición. también puede elegir un valor constante lo suficientemente bajo como para no confundirse con un valor real, pero eso supone que tiene algún conocimiento de sus datos.