2012-05-19 8 views
5

estoy tratando de obtener el derecho siguiente configuración:Cómo hacer cumplir una orden de llamar a los destructores

una aplicación dada (con múltiples archivos fuente, unidades de compilación) tiene variables globales de tipo class A definido de muchas unidades de compilación. Estos deberían ser "administrados" por un nuevo para introducir class B (donde solo debería existir 1 instancia) en el sentido de que al crearse ellos mismos "se registran" en la clase B y en la destrucción "cerrar sesión".

Configurar las cosas para que los constructores funcionen es bastante directo. Uno puede usar:

types.h:

class B { 
    static B& Instance() { 
    static B singleton; 
    return singleton; 
    } 
    void registerA(const A& a) { 
    // whatever 
    } 
}; 


class A { 
    A() { B::Instance().registerA(this); } 
}; 

Como llegar a los destructores ¿verdad? Si se utiliza:

class A { 
    A() { B::Instance().registerA(this); } 
    ~A() { B::Instance().signoffA(this); } 
}; 

continuación, el destructor de B puede ser llamado antes de que el destructor de A. Luego, la instancia de la clase A cierra la sesión en una instancia recién creada de B.

El caso de prueba sería una configuración multi fuente de archivo con las definiciones de los casos de class A en un espacio de nombres:

file1.cc

#include "types.h" 
namespace C { 
    A a; 
} 

file2.cc

#include "types.h" 
namespace C { 
    A b; 
} 

supongo que el puede hacer tales cosa fácil con los indicadores inteligentes Boost. Sin embargo, si es posible, me gustaría evitar el uso de bibliotecas adicionales para mantener la dependencia lo más bajo posible.

Una cosa que podría ayudar: Todas las variables globales están en un espacio de nombres nombrado.

+0

Corrija la sangría y el alcance. –

+0

Además, considere la creación de un breve caso de prueba coherente para ilustrar dónde se crea su instancia 'A' en relación con todo lo demás. Es un poco confuso actualmente. –

+0

Tenga en cuenta que 'register' es una palabra clave en C++ y C, y por lo tanto su código no se compila. –

Respuesta

4

Creo que estás bien. Aquí es en 3.6.3 "Terminación":

Si la realización del constructor o inicialización dinámica de un objeto con una duración de almacenamiento estático se secuencia antes de la de otro, la realización del destructor de la segunda se secuencia antes de la iniciación del destructor del primero.

Suponga que tiene la siguiente configuración:

struct A; 

struct B 
{ 
    static B & get() { static B impl; return impl; } 
    void registrate(A *); 

private: 
    B() { /* complex stuff */ } 
    // ... 
}; 

struct A { A() { B::get().registrate(this); } }; 

A a1; 

Ahora lo que pase, el primer constructor de un objeto de tipo estático A llamará B::get(), cuyas secuencias de la construcción de la impl objeto estático antes de la finalización del primer A -constructor. Por la cláusula anterior, esto garantiza que el destructor del B impl -objeto está secuenciado después de todos los A -destructores.

+0

¿No se refiere la declaración citada al caso en que ambos objetos tienen una duración de almacenamiento estática? En mi caso, solo uno de ellos es 'estático'. – ritter

+0

No lo entiendo: .. "el primer constructor de un tipo A estático". 'A' no es estático. – ritter

+0

@Frank: "estático" no significa lo que piensas. Todo en el ejemplo tiene una duración de almacenamiento estática. La palabra clave 'static 'es solo una de las muchas, muchas formas de hacer que un objeto tenga una duración de almacenamiento estática. –

2

La instancia B es estática, por lo que sobrevivirá cualquier instancia A creada después de que se haya creado el singleton B.

+0

Esto es cierto si todos los objetos están en la misma unidad de compilación. Este no es el caso aquí. No estoy seguro de si la destrucción de objetos "estáticos" se aplaza también en las unidades de compilación – ritter

+0

@Frank. No veo cómo no se aplicaría en las unidades de compilación. – juanchopanza

+0

Sí, la configuración está bien. Pero la razón es el orden de los constructores de llamadas y el hecho de que es estático. Si se refiere a ambas circunstancias al mismo tiempo, tiene razón – ritter

Cuestiones relacionadas