Pregunta

Alguien me habló de un estilo de C++ diferencia en su equipo.Yo tengo mi propio punto de vista sobre el tema, pero me interesaría por pros y contras procedentes de todo el mundo.

Así, en caso de tener una propiedad de la clase que se desea exponer a través de dos captadores, uno de lectura/escritura, y el otro, readonly (es decir,no hay un método establecido).Hay al menos dos formas de hacerlo:

class T ;

class MethodA
{
   public :
      const T & get() const ;
      T & get() ;

      // etc.
} ;

class MethodB
{
   public :
      const T & getAsConst() const ;
      T & get() ;

      // etc.
} ;

¿Cuáles serían los pros y los contras de cada método?

Estoy interesado más por C++ técnico/razones semánticas, pero el estilo razones son bienvenidos.

Tenga en cuenta que MethodB tiene un gran inconveniente técnico (sugerencia:en el código genérico).

¿Fue útil?

Solución

Bien, por un lado, getAsConst debe se llama cuando el puntero 'this' es const-no cuando usted quiere recibir un objeto const.Así, junto a otras cuestiones, es sutilmente el nombre correcto.(Usted puede llamar cuando 'esto' no es constante, pero que no es ni aquí ni allí.)

Ignorando que, getAsConst gana nada, y pone una carga excesiva a los desarrolladores el uso de la interfaz.En lugar de simplemente llamar "get" y a sabiendas de que está recibiendo lo que necesita, ahora él tiene que determinar si es o no es en la actualidad el uso de una constante variable, y si el nuevo objeto que él está agarrando necesita ser const.Y más tarde, si ambos objetos se convierten en no-const debido a que algunos de refactorización, él tiene que cambiar su llamada.

Otros consejos

C++ debe ser perfectamente capaz de hacer frente con el método a en casi todas las situaciones.Yo siempre lo uso y nunca he tenido un problema.

El método B es, en mi opinión, un caso de violación de OnceAndOnlyOnce.Y, ahora debe ir a averiguar si usted está tratando con referencia constante al escribir el código que se compila por primera vez.

Supongo que esta es una estilística cosa - técnicamente ambas obras, pero MethodA hace que el compilador de trabajo un poco más difícil.Para mí, es una buena cosa.

Personalmente, yo prefiero el primer método, porque hace de una forma más coherente de la interfaz.También, me getAsConst() suena tan tonto como getAsInt().

En una nota diferente, usted realmente debe pensar dos veces antes de devolver un no-const de referencia o un no-const puntero a un miembro de datos de su clase.Esta es una invitación para la gente para explotar el funcionamiento interno de su clase, que idealmente debe ser ocultado.En otras palabras, se rompe la encapsulación.Me gustaría utilizar un get() const y un set(), y devolver una referencia no const sólo si no hay otra manera, o cuando lo que realmente tiene sentido, como para dar acceso de lectura/escritura a un elemento de una matriz o una matriz.

Dado el estilo precedente establecido por la biblioteca estándar (es decir, comenzar() y() const para citar sólo un ejemplo), debería ser obvio que Un método es la elección correcta.Me pregunta la persona cordura que elige el método B.

Así, el primer estilo en general es preferible.

Hacemos uso de una variación de la segunda de estilo un poco en el código base que estoy trabajando, porque queremos una gran distinción entre const y no-const de uso.

En mi ejemplo concreto, hemos getTessellation y getMutableTessellation.Se implementa con un copy-on-write puntero.Por motivos de rendimiento queremos que la const versión que se va a utilizar siempre que sea posible, por lo tanto, hacer el nombre más corto, y lo hacemos con un nombre diferente para que la gente no accidentalmente causa una copia cuando no se les va a escribir de todos modos.

Mientras parece que tu pregunta sólo se dirige a un método, yo estaría encantado de dar mi opinión sobre el estilo.Personalmente, para el estilo razones, prefiero la primera.La mayoría de los IDEs emergente de la firma de tipo de funciones para.

Yo prefiero la primera.Se ve mejor en el código cuando dos cosas que básicamente hacen lo mismo el mismo aspecto.También, es raro que usted no tiene una const objeto, pero quiero llamar la const método, por lo que no es mucho de un consern (y en el peor de los casos, usted sólo necesita un const_cast<>).

La primera permite a los cambios en el tipo de variable (si es const o no), sin más modificación del código.Por supuesto, esto significa que no hay ninguna notificación para el desarrollador que esto puede haber cambiado desde la ruta prevista.Así que si el valor de ser capaz de refactorizar, o tener la red de seguridad adicional.

La segunda es algo relacionado con la notación húngara que yo personalmente NO así que voy a seguir con el primero método.

No me gusta la notación húngara porque añade redundancia, que por lo general detesto en la programación.Es sólo mi opinión.

Desde que ocultar los nombres de las clases, este alimento para el pensamiento sobre el estilo puede o no puede aplicar:

¿Tiene sentido decir que estos dos objetos, MethodA y MethodB, para "obtener" o "getAsConst"?Podría usted enviar "get" o "getAsConst" como mensajes a cualquiera de los dos objetos?

A mi modo de ver, como el remitente del mensaje / invocador del método, usted son el conseguir el valor;así que en respuesta a esta "obtener" el mensaje, se envía un mensaje a MethodA / MethodB, el resultado de lo que es el valor que necesitas.

Ejemplo:Si el llamador de MethodA es decir, un servicio en SOA, y MethodA es un repositorio, a continuación, dentro del servicio de la get_A(), llamada MethodA.find_A_by_criteria(...).

El tecnológico importante inconveniente de MethodB que he visto es que al aplicar el código genérico para ello, debemos doblar el código para controlar tanto la const y la no-const versión.Por ejemplo:

Digamos que T es una orden-capaz de objeto (es decir, podemos comparar a los objetos de tipo T con el operador <), y supongamos que queremos hallar el máximo entre dos MethodA (resp.dos MethodB).

Para MethodA, todos necesitamos el código es:

template <typename T>
T & getMax(T & p_oLeft, T & p_oRight)
{
   if(p_oLeft.get() > p_oRight.get())
   {
      return p_oLeft ;
   }
   else
   {
      return p_oRight ;
   }
}

Este código funcionará tanto con const objetos y no const objetos de tipo T:

// Ok
const MethodA oA_C0(), oA_C1() ;
const MethodA & oA_CResult = getMax(oA_C0, oA_C1) ;

// Ok again
MethodA oA_0(), oA_1() ;
MethodA & oA_Result = getMax(oA_0, oA_1) ;

El problema viene cuando queremos aplicar este sencillo código para algo siguientes a la MethodB convención:

// NOT Ok
const MethodB oB_C0(), oB_C1() ;
const MethodB & oB_CResult = getMax(oB_C0, oB_C1) ; // Won't compile

// Ok
MethodA oB_0(), oB_1() ;
MethodA & oB_Result = getMax(oB_0, oB_1) ;

Para el MethodB para trabajar en const y no-const versión, se deben utilizar los que ya están definidas getMax, pero se añade la siguiente versión de getMax:

template <typename T>
const T & getMax(const T & p_oLeft, const T & p_oRight)
{
   if(p_oLeft.getAsConst() > p_oRight.getAsConst())
   {
      return p_oLeft ;
   }
   else
   {
      return p_oRight ;
   }
}

Conclusión, por no confiar en el compilador en const-ness uso, nos carga a nosotros mismos con la creación de dos funciones genéricas, cuando debería haber sido suficiente.

Por supuesto, con suficiente paranoia, la secondth función de la plantilla debería haber sido llamado getMaxAsConst...Y por lo tanto, el problema podría propagarse a través de todo el código...

:-p

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top