2012-02-03 29 views
10

Estoy buscando una solución elegante para implementar el equivalente de la declaración que usa C# en C++. Idealmente, la sintaxis resultante debería ser simple de usar y leer.Implementando el equivalente en C++ de C# usando la declaración

C# Usando datos de los estados están aquí - http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

No estoy seguro de si la solución sería el uso de punteros de función con los destructores de las clases, algún tipo de programación de plantilla inteligente o incluso la programación plantilla de meta. Básicamente, no sé por dónde empezar con esto ...

+13

Me han dicho RAII cubre esto. –

+1

Como dijo Anthony, el uso de RAII automáticamente hará esto por usted y, en mi opinión, hace que el código sea mucho más limpio que el patrón de uso. – Mranz

+4

Desde mi punto de vista, la palabra clave 'using' es solo un remedio mediocre para no tener RAII en primer lugar. Entonces, no tratarás de emularlo. – Andre

Respuesta

24

No necesita implementar esto en C++ porque el patrón estándar de RAII ya hace lo que necesita.

{ 
    ofstream myfile; 
    myfile.open("hello.txt"); 
    myfile << "Hello\n"; 
} 

Cuando termina el ámbito de bloque, myfile se destruye que cierra el archivo y libera todos los recursos asociados con el objeto.

La razón por la cual la declaración using existe en C# es para proporcionar algo de azúcar sintáctico alrededor de try/finally y IDisposable. Simplemente no es necesario en C++ porque los dos idiomas son diferentes y el problema se resuelve de manera diferente en cada idioma.

+2

Esto es muy superior al C# 'using', y también funciona con objetos .NET en C++/CLI. La sintaxis de C++ es mucho mejor porque, si bien debe recordar usar la sintaxis de semántica de valores: (1) Puede usarla para cada tipo, implemente o no 'IDisposable' o no, o para interfaces, diferentes objetos pueden o no, y (2) Funciona para los miembros de la clase. –

+1

Creo que no se trata de una cuestión de mejor o peor, es una cuestión de qué herramientas tiene para enfrentar el problema en su entorno. C++ usa el montón como gestión de memoria y también se apila, pero no tiene recolección de basura, así que esa es la diferencia, la administración de memoria retrasada de GC, que tiene sus propias ventajas, entonces ¿qué debo hacer para trabajar en ese contexto? aquí no somos equipos deportivos diferentes, somos desarrolladores que manejan diferentes tecnologías ... –

2

Eche un vistazo al uso de std :: auto_ptr <> para manejar la limpieza de las instancias asignadas y asignadas a un puntero dentro de un alcance particular; de lo contrario, cualquier variable declarada dentro de un alcance específico simplemente será destruida cuando salir de dicho alcance.

{ 
    SomeClass A; 
    A.doSomething(); 
} // The destructor for A gets called after exiting this scope here 

{ 
    SomeClass* pA = new SomeClass(); 
    std::auto_ptr<SomeClass> pAutoA(pA); 
    pAutoA->doSomething(); 
} // The destructor for A also gets called here, but only because we 
    // declared a std::auto_ptr<> and assigned A to it within the scope. 

Ver http://en.wikipedia.org/wiki/Auto_ptr un poco más de información sobre std :: auto_ptr <>

+2

'std :: auto_ptr' está en desuso, use' std :: unique_ptr' en su lugar – Praetorian

+0

Es bueno saberlo, gracias. La mayoría de los días, generalmente me apego a las bibliotecas de Boost de todos modos ... – hatboyzero

2

Un patrón RAII más detallado que se asemeja using C# 's se puede lograr con un simple macro.

#define Using(what, body) { what; body; } 

Using(int a=9, 
{ 
    a++; 
}) 

a++; // compile error, a has gone out of scope here 

Nota debemos usar mayúscula "Uso" para evitar una colisión con C++ 's construido en el 'uso' declaración que, obviamente, tiene un significado diferente.

+0

Me gusta esto porque me gusta la naturaleza explícita de 'usar'. En cuanto a la macro en sí, me gusta más esta: https://tedclancy.wordpress.com/2015/07/04/raii-helper-macro/. – Dina

0

vistazo a lo siguiente:

#include <iostream> 

using namespace std; 


class Disposable{ 
private: 
    int disposed=0; 
public: 
    int notDisposed(){ 
     return !disposed; 
    } 

    void doDispose(){ 
     disposed = true; 
     dispose(); 
    } 

    virtual void dispose(){} 

}; 



class Connection : public Disposable { 

private: 
    Connection *previous=nullptr; 
public: 
    static Connection *instance; 

    Connection(){ 
     previous=instance; 
     instance=this; 
    } 

    void dispose(){ 
     delete instance; 
     instance = previous; 
    } 
}; 

Connection *Connection::instance=nullptr; 


#define using(obj) for(Disposable *__tmpPtr=obj;__tmpPtr->notDisposed();__tmpPtr->doDispose()) 

int Execute(const char* query){ 
    if(Connection::instance == nullptr){ 
     cout << "------- No Connection -------" << endl; 
     cout << query << endl; 
     cout << "------------------------------" << endl; 
     cout << endl; 

     return -1;//throw some Exception 
    } 

    cout << "------ Execution Result ------" << endl; 
    cout << query << endl; 
    cout << "------------------------------" << endl; 
    cout << endl; 

    return 0; 
} 

int main(int argc, const char * argv[]) { 

    using(new Connection()) 
    { 
     Execute("SELECT King FROM goats");//out of the scope 
    } 

    Execute("SELECT * FROM goats");//in the scope 

} 
Cuestiones relacionadas