2010-04-22 18 views
13

I answered este question y Potatoswatteranswered también como¿Qué es "objeto centinela" en C++?

El moderno equivalente de C++ sería un objeto centinela: construirla en el principio de una función, con su llamado implementar constructor(), y a su regreso (o salida anormal), su destructor implementa

No estoy familiarizado con el uso de objetos centinela en C++. Pensé que estaban limitados a los flujos de entrada y salida.

¿Podría alguien explicarme acerca de los objetos Centinela C++ y cómo usarlos como un interceptor alrededor de uno o más métodos en una clase?

es decir, cómo hacerlo?

Sentry objects son muy similares indeed. Por un lado se requieren instancias explícita (y siendo pasado este), pero por otro lado se pueden añadir a ellos para que cheque no sólo las invariantes de esta categoría pero algunos pre/condiciones de correos para la función a mano.

+1

Aparte de esta pregunta es muy probable que sea una tontería, por favor, no etiquete sus preguntas con ninguna etiqueta relacionada con Visual Studio cuando haga preguntas genéricas de C++. –

+1

@Pavel Hice la búsqueda y no encontré –

+0

@Pavel lo siento es mi primera pregunta –

Respuesta

15

El objeto centinela es un patrón, pero no estoy seguro de cuál de los siguientes (tal vez todos).

Los programas de C++ a menudo se basan en gran medida en el conocimiento cuando se destruye exactamente un objeto (posiblemente de una clase definida por el usuario), es decir, cuando se llama a su destructor. Este no es el caso para los idiomas con recolección de basura.

Esta técnica se utiliza, por ejemplo, para adoptar el paradigma "Inicialización de adquisición de recursos es inicialización": adquiere recursos cuando se llama a un constructor de objetos, y el compilador llama automáticamente a su destructor para liberar recursos tanto normales como anormales (excepcionales) situaciones (marque this question).

Los lugares más comunes donde se puede utilizar el conocimiento del tiempo de construcción/destrucción son

  • Bloques: un destructor para "apilar-asignado" objeto se llama al final del bloque

    void function() 
    { Class foo = Object(resource); 
        other_operations(); 
    } // destructor for foo is called here 
    
  • Llamadas a funciones: "stack-allocation" también ocurre cuando llama a una función

    void function() 
    { another_function (Class(resource) ); 
        // destructor for the unnamed object is called 
        // after another_function() returns (or throws) 
        other_operations(); 
    } 
    
  • Construcción/Destrucción del objeto que contiene:

    class Foo 
    { Class sentry; 
        public: Foo() 
        { // Constructor for sentry is called here 
         something(); 
        }   
        public: ~Foo() 
        { 
         something(); 
        } // destructor for sentry is called here 
    }; 
    

En STL hay una clase llamada sentry (más exactamente, istream::sentry), que implementa el tercer patrón de los descritos anteriormente . Así que creo que eso es lo que algunos programadores llaman "objeto centinela".

Pero, de hecho, cualquiera de los objetos anteriores de la clase Class se puede llamar "objeto centinela". Son "centinelas" porque aseguran que estos esquivos destructores de objetos no se pierdan incluso si algo arroja una excepción (por lo que son como guardianes del bloque/clase, de tipo).

Más ejemplos de objetos sentry están en ese RAII question.


Puede ver una relación con la programación orientada a aspectos; estos objetos son algo así como "aspectos", con puntos de corte "al principio/final del bloque envolvente", "en la construcción/destrucción del objeto contenedor", etc. Pero estos "aspectos" tienen a presente en el código que aspectan. Por lo tanto, son menos "aspecto" en comparación con la funcionalidad original call/return; en cambio, un objeto centinela se debe insertar a cada función de la clase:

class X{ 
    struct Sentry { 
    Sentry() { /* call() */} 
    ~Sentry() { /* return() */}; 
    }; 

    void member_function() 
    { Sentry(); 
    /* operations */ 
    } 

    void another_member_function() 
    { Sentry(); 
    /* operations */ 
    } 
}; 
+1

+1 thx por tomarse el tiempo para explicar tan bien –

+5

@Romian, no hay problema, estoy haciendo todo lo posible para posponer las cosas haciendo mi trabajo actual> _ < –

+2

No todos sabemos esto ... ':)' – sbi

2

Here es un ejemplo de una clase centinela que restablece una variable a su valor anterior.

+0

No veo la respuesta a la pregunta en la publicación. ¿Es un objeto centinela un patrón? –

+0

@Romain: Entonces leí mal su pregunta. pensé que estabas preguntando qué es un objeto centinela y cómo usarlo. – sbi

+0

@Romain: sí, es un patrón y no una clase en particular. Incluso puede usar una clase anónima local, no derivada dentro de la función como centinela. – Potatoswatter

3

La diferencia con AOP es que tiene que ser hecho cooperativamente poniendo el centinela de forma explícita en algún lugar dentro del cuerpo de la función o la definición de clase.

No puede capturar las llamadas sin modificar la función o clase específica.