2012-02-03 14 views
10

Sto cercando una soluzione elegante per implementare l'equivalente dell'istruzione C# usando in C++. Idealmente la sintassi risultante dovrebbe essere semplice da usare e leggere.Implementazione di C++ equivalente di C# usando la dichiarazione

C# utilizzando i economico sono qui - http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

Non sono sicuro se la soluzione potrebbe essere quella di utilizzare puntatori a funzione con distruttori sulle classi, una qualche forma di programmazione modello intelligente o addirittura di programmazione modello di meta. Fondamentalmente non so da dove cominciare ...

+13

Mi è stato detto RAII si occupa di questo. –

+1

Come ha detto Anthony, l'uso di RAII lo farà automaticamente per te, e imho, rende il codice molto più pulito rispetto al pattern di utilizzo. – Mranz

+4

Dal mio punto di vista, la parola chiave 'using' è solo un rimedio mediocre per non avere RAII in primo luogo. Quindi, non cercherai di emularlo. – Andre

risposta

24

Non è necessario implementare questo in C++ perché il modello standard di RAII già fa ciò che ti serve.

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

Quando l'ambito blocco termina, viene distrutto myfile che chiude il file e libera tutte le risorse associate all'oggetto.

Il motivo per cui l'istruzione using esiste in C# è quella di fornire un po 'di zucchero sintattico attorno a try/finally e IDisposable. Semplicemente non è necessario in C++ perché le due lingue differiscono e il problema è risolto in modo diverso in ogni lingua.

+2

Questo è di gran lunga superiore al C# 'using', e funziona anche con oggetti .NET in C++/CLI. La sintassi C++ è di gran lunga migliore, anche se devi ancora ricordare di usare la sintassi della semantica del valore: (1) Puoi usarla per ogni tipo, indipendentemente dal fatto che implementi 'IDisposable', o no, o per le interfacce, diversi oggetti possono o non può, e (2) Funziona per i membri della classe. –

+1

Penso che non sia una questione di bene o di male, è una questione di quali strumenti hai a che fare con il problema nel tuo ambiente. Il C++ usa l'heap come gestione della memoria e anche lo stack, ma non ha la garbage collection, quindi questa è la differenza, GC ha ritardato la gestione della memoria, che ha i suoi vantaggi, quindi cosa dovrei fare per lavorare in quel contesto? non siamo diversi team sportivi qui, siamo sviluppatori che si occupano di diverse tecnologie ... –

2

Vorrei dare un'occhiata all'utilizzo di std :: auto_ptr <> per gestire la pulizia di tutte le istanze allocate e assegnate a un puntatore all'interno di un particolare ambito - altrimenti, qualsiasi variabile dichiarata all'interno di uno specifico ambito verrà semplicemente distrutta quando uscire da detto ambito.

{ 
    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. 

Vedi http://en.wikipedia.org/wiki/Auto_ptr per un po 'più di informazioni sul std :: auto_ptr <>

+2

'std :: auto_ptr' è deprecato, usa' std :: unique_ptr' invece – Praetorian

+0

Buono a sapersi, grazie. La maggior parte dei giorni, di solito mi attengo alle librerie Boost comunque ... – hatboyzero

2

Un modello RAII più dettagliato che assomiglia a C# s 'istruzione using può essere realizzato con una semplice macro.

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

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

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

Nota dobbiamo usare un capitale "Uso" per evitare una collisione con C++ 's costruito nel 'usando' dichiarazione che ovviamente ha un significato diverso.

+0

Mi piace perché mi piace la natura esplicita dell '"uso". Per quanto riguarda la macro stessa, mi piace questa migliore: https://tedclancy.wordpress.com/2015/07/04/raii-helper-macro/. – Dina

0

un'occhiata al seguente:

#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 

}