txt secuenciales manejo lenguaje leer fscanf ejercicios como binarios archivos archivo aleatorio acceso c++ coding-style typedef

c++ - secuenciales - manejo de archivos en c pdf



Tipos de archivos internos en C++: ¿buen estilo o mal estilo? (9)

Algo que últimamente me he encontrado haciendo la tarea es declarar typedefs relevante para una clase particular dentro de esa clase, es decir,

class Lorem { typedef boost::shared_ptr<Lorem> ptr; typedef std::vector<Lorem::ptr> vector; // // ... // };

Estos tipos se usan en otro lugar del código:

Lorem::vector lorems; Lorem::ptr lorem( new Lorem() ); lorems.push_back( lorem );

Razones por las que me gusta:

  • Reduce el ruido introducido por las plantillas de clase, std::vector<Lorem> convierte en Lorem::vector , etc.
  • Sirve como una declaración de intenciones: en el ejemplo anterior, la clase Lorem está destinada a ser contada como referencia mediante boost::shared_ptr y almacenada en un vector.
  • Permite que la implementación cambie, es decir, si Lorem se tuvo que cambiar para que se contara de manera intrusa (mediante boost::intrusive_ptr ) en una etapa posterior, esto tendría un impacto mínimo en el código.
  • Creo que se ve "más bonito" y podría decirse que es más fácil de leer.

Razones por las que no me gusta:

  • A veces hay problemas con las dependencias: si desea incrustar, por ejemplo, un Lorem::vector dentro de otra clase pero solo necesita (o desea) reenviar declarar Lorem (en lugar de introducir una dependencia en su archivo de encabezado), entonces termina tener que usar los tipos explícitos (por ejemplo, boost::shared_ptr<Lorem> lugar de Lorem::ptr ), que es un poco inconsistente.
  • Puede no ser muy común, y por lo tanto, más difícil de entender?

Intento ser objetivo con mi estilo de codificación, por lo que sería bueno obtener algunas otras opiniones sobre él para poder diseccionar mi pensamiento un poco.


Sirve como una declaración de intenciones: en el ejemplo anterior, la clase Lorem está destinada a ser contada como referencia mediante boost :: shared_ptr y almacenada en un vector.

Esto es exactamente lo que no hace.

Si veo ''Foo :: Ptr'' en el código, no tengo absolutamente ninguna idea de si es un shared_ptr o un Foo * (STL tiene :: puntero typedefs que son T *, recuerda) o lo que sea. Esp. si es un puntero compartido, no proporciono un typedef en absoluto, pero mantengo el uso de shared_ptr explícitamente en el código.

En realidad, casi nunca utilizo typedefs fuera de la metaprogramación de plantillas.

El STL hace este tipo de cosas todo el tiempo

El diseño de STL con conceptos definidos en términos de funciones de miembro y typedefs anidados es un callejón sin salida histórico, las bibliotecas de plantillas modernas usan clases de funciones y rasgos libres (véase Boost.Graph), porque estos no excluyen tipos incorporados de modelar el concepto y porque hace más fáciles los tipos de adaptación que no fueron diseñados teniendo en cuenta los conceptos de las bibliotecas de plantillas.

No use el STL como una razón para cometer los mismos errores.


Actualmente estoy trabajando en código, que usa intensivamente este tipo de typedefs. Hasta ahora eso está bien.

Pero noté que a menudo hay tipos de letra iterativos, las definiciones se dividen entre varias clases, y nunca sabes realmente con qué tipo estás tratando. Mi tarea es resumir el tamaño de algunas estructuras de datos complejas ocultas detrás de estos typedefs, por lo que no puedo confiar en las interfaces existentes. En combinación con tres a seis niveles de espacios de nombres anidados, se vuelve confuso.

Entonces, antes de usarlos, hay algunos puntos que se deben considerar

  • ¿Alguien más necesita estos typedefs? ¿La clase se usa mucho en otras clases?
  • ¿Acorto el uso u oculto la clase? (En caso de ocultarse, también podría pensar en interfaces).
  • ¿Hay otras personas trabajando con el código? ¿Cómo lo hicieron? ¿Pensarán que es más fácil o se confundirán?

Creo que es un estilo excelente, y lo uso yo mismo. Siempre es mejor limitar el alcance de los nombres tanto como sea posible, y el uso de clases es la mejor manera de hacerlo en C ++. Por ejemplo, la biblioteca estándar de C ++ hace un uso intensivo de typedefs dentro de las clases.


Cuando el typedef se usa solo dentro de la clase misma (es decir, se declara como privado), creo que es una buena idea. Sin embargo, por exactamente las razones que usted da, no lo usaría si los typedef necesitan ser conocidos fuera de la clase. En ese caso, recomiendo moverlos fuera de la clase.


El STL hace este tipo de cosas todo el tiempo: los typedefs son parte de la interfaz para muchas clases en el STL.

reference iterator size_type value_type etc...

son todos los typedefs que son parte de la interfaz para varias clases de plantilla STL.


Los Typdefs son definitivamente un buen estilo. Y todas tus "razones que me gustan" son buenas y correctas.

Acerca de los problemas que tienes con eso. Bueno, la declaración avanzada no es un santo grial. Simplemente puede diseñar su código para evitar dependencias de múltiples niveles.

Puede mover typedef fuera de la clase, pero Class :: ptr es mucho más bonito que ClassPtr y yo no hago esto. Es como con espacios de nombres como para mí: las cosas permanecen conectadas dentro del alcance.

A veces lo hice

Trait<Loren>::ptr Trait<Loren>::collection Trait<Loren>::map

Y puede ser predeterminado para todas las clases de dominio y con cierta especialización para ciertas.



Otro voto para esto es una buena idea. Empecé a hacer esto cuando escribía una simulación que tenía que ser eficiente, tanto en tiempo como en espacio. Todos los tipos de valores tenían un tipodef de Ptr que comenzó como un puntero compartido de impulso. Luego hice algunos perfiles y cambié algunos de ellos para impulsar un puntero intrusivo sin tener que cambiar el código donde se usaron estos objetos.

Tenga en cuenta que esto solo funciona cuando sabe dónde se usarán las clases y que todos los usos tienen los mismos requisitos. No utilizaría esto en el código de la biblioteca, por ejemplo, porque no puede saber al escribir la biblioteca el contexto en el que se utilizará.


Recomiendo mover esos typedefs fuera de la clase. De esta forma, elimina la dependencia directa de las clases de punteros y vectores compartidos y puede incluirlos solo cuando sea necesario. A menos que use esos tipos en su implementación de clase, considero que no deberían ser de tipo interno.

Los motivos que le gustan aún se corresponden, ya que se resuelven mediante el aliasing tipo a través de typedef, no mediante su declaración dentro de su clase.