¿Alguien puede señalarme algunos buenos recursos para comprender y usar clases anidadas? Tengo algunos materiales como Principios de programación y cosas como este IBM Knowledge Center - Clases anidadas
Pero todavía tengo problemas para entender su propósito. ¿Alguien podría ayudarme por favor?
c++
nested
inner-classes
con gafas
fuente
fuente
typedef
. 3. porque añaden un nivel adicional de sangrado en un ambiente donde evitando largas filas ya es difícil 4. porque está declarando dos objetos separados conceptualmente en una solaclass
declaración, etc.Respuestas:
Las clases anidadas son geniales para ocultar detalles de implementación.
Lista:
Aquí no quiero exponer Node ya que otras personas pueden decidir usar la clase y eso me impediría actualizar mi clase ya que todo lo expuesto es parte de la API pública y debe mantenerse para siempre . Al hacer que la clase sea privada, no solo oculto la implementación, también digo que es mía y que puedo cambiarla en cualquier momento para que no pueda usarla.
Mire
std::list
ostd::map
todos contienen clases ocultas (¿o sí?). El punto es que pueden o no, pero debido a que la implementación es privada y oculta, los constructores de STL pudieron actualizar el código sin afectar la forma en que usó el código o dejar un montón de equipaje viejo alrededor del STL porque necesitan para mantener la compatibilidad con algunos tontos que decidieron que querían usar la clase Node que estaba oculta en su interiorlist
.fuente
Node
, no debería exponerse en el archivo de encabezado.detail
convención: en lugar de depender de tales convenciones que uno debe tener en cuenta, es mejor depender del compilador que los rastrea por usted.Las clases anidadas son como las clases regulares, pero:
Algunos ejemplos:
Clase de anidación pública para ponerla en un ámbito de clase relevante
Suponga que desea tener una clase
SomeSpecificCollection
que agregue objetos de claseElement
. Entonces puedes:declara dos clases:
SomeSpecificCollection
yElement
- malo, porque el nombre "Elemento" es lo suficientemente general como para causar un posible choque de nombresintroducir un espacio de nombres
someSpecificCollection
y declarar clasessomeSpecificCollection::Collection
ysomeSpecificCollection::Element
. No hay riesgo de choque de nombres, pero ¿puede ser más detallado?declara dos clases globales
SomeSpecificCollection
ySomeSpecificCollectionElement
, que tiene inconvenientes menores, pero probablemente esté bien.declarar clase global
SomeSpecificCollection
y claseElement
como su clase anidada. Luego:SomeSpecificCollection
usted se refiere a soloElement
, y en todas partes comoSomeSpecificCollection::Element
- que se ve + - igual que 3., pero más claroSomeSpecificCollection
también es una clase.En mi opinión, la última variante es definitivamente el diseño más intuitivo y, por lo tanto, el mejor.
Permítanme enfatizar: no es una gran diferencia hacer dos clases globales con nombres más detallados. Es solo un pequeño detalle, pero en mi opinión, hace que el código sea más claro.
Introducir otro ámbito dentro de un ámbito de clase
Esto es especialmente útil para introducir typedefs o enumeraciones. Voy a publicar un ejemplo de código aquí:
Uno entonces llamará:
Pero cuando se miran las propuestas de finalización de código
Product::
, a menudo se obtienen todos los valores de enumeración posibles (BOX, FANCY, CRATE) enumerados y es fácil cometer un error aquí (las enumeraciones fuertemente tipadas de C ++ 0x resuelven eso, pero no importa )Pero si introduce un alcance adicional para esas enumeraciones que usan clases anidadas, las cosas podrían verse así:
Entonces la llamada se ve así:
Luego, al escribir
Product::ProductType::
un IDE, se obtendrán solo las enumeraciones del alcance deseado sugerido. Esto también reduce el riesgo de cometer un error.Por supuesto, esto puede no ser necesario para clases pequeñas, pero si uno tiene muchas enumeraciones, entonces facilita las cosas para los programadores del cliente.
De la misma manera, podría "organizar" un gran grupo de typedefs en una plantilla, si alguna vez tuvo la necesidad de hacerlo. Es un patrón útil a veces.
El idioma de PIMPL
El PIMPL (abreviatura de puntero a IMPLementation) es una expresión útil para eliminar los detalles de implementación de una clase del encabezado. Esto reduce la necesidad de volver a compilar clases según el encabezado de la clase siempre que cambie la parte de "implementación" del encabezado.
Por lo general, se implementa usando una clase anidada:
Xh:
X.cpp:
Esto es particularmente útil si la definición de clase completa necesita la definición de tipos de alguna biblioteca externa que tiene un archivo de encabezado pesado o simplemente feo (tome WinAPI). Si usa PIMPL, puede incluir cualquier funcionalidad específica de WinAPI solo en
.cpp
y nunca incluirla.h
.fuente
struct Impl; std::auto_ptr<Impl> impl;
Este error fue popularizado por Herb Sutter. No use auto_ptr en tipos incompletos, o al menos tome precauciones para evitar la generación de código incorrecto.auto_ptr
tipo incompleto en la mayoría de las implementaciones, pero técnicamente es UB a diferencia de algunas de las plantillas en C ++ 0x (por ejemplounique_ptr
) donde se ha hecho explícito que el parámetro de plantilla puede ser un tipo incompleto y donde exactamente el tipo debe estar completo. (por ejemplo, uso de~unique_ptr
)T
de plantilla deunique_ptr
puede ser un tipo incompleto".enum class
.No uso muchas clases anidadas, pero las uso de vez en cuando. Especialmente cuando defino algún tipo de tipo de datos, y luego quiero definir un functor STL diseñado para ese tipo de datos.
Por ejemplo, considere una
Field
clase genérica que tiene un número de identificación, un código de tipo y un nombre de campo. Si deseo buscar unovector
de estosField
s por número de identificación o nombre, podría construir un functor para hacerlo:Luego, el código que necesita buscar estos
Field
s puede usar elmatch
ámbito dentro de laField
propia clase:fuente
Se puede implementar un patrón Builder con clase anidada . Especialmente en C ++, personalmente lo encuentro semánticamente más limpio. Por ejemplo:
Más bien que:
fuente