2008-12-03 6 views

Répondre

31

En supposant que vous voulez dire C++/CLI (pas l'ancien Managed C++), les éléments suivants sont vos options:

(1) Mimic un utilisant-bloc avec l'aide d'objets automatique/stackbased:

{ 
    SqlConnection conn(connectionString); 
} 

Cela appellera le Destructeur de l'objet "conn" lorsque le bloc suivant sera terminé. Qu'il s'agisse de la fonction englobante ou d'un bloc que vous ajoutez manuellement pour limiter la portée, cela n'a pas d'importance.

(2) appeler Explicitement "disposer", à savoir détruire l'objet:

SqlConnection^ conn = nullptr; 
try 
{ 
    conn = gcnew SqlConnection(conntectionString); 

} 
finally 
{ 
    if (conn != nullptr) 
    delete conn; 
} 

Le premier serait le remplacement direct "à l'aide". Le second est une option, généralement vous n'aurez pas besoin de le faire à moins que vous ne passiez la référence à un autre endroit.

+0

La première syntaxe (en utilisant des accolades nues pour limiter la portée) garantit-elle d'appeler Dispose même si vous quittez la portée en lançant une exception? Je ne pensais pas que c'était le cas, mais bien sûr je peux me tromper. – Coderer

+0

Oui c'est garanti. En effet, c'est l'idée ici. Les destructeurs d'objets alloués à la pile sont appelés lorsque la portée englobante se termine (soit régulièrement, soit prématurément par une exception) - en fait cela n'a rien à voir avec la gestion ou pas. C'est aussi de cette façon en code natif. –

+0

@ Christian.K, êtes-vous sûr de "à moins que vous ne passiez la référence ailleurs"? Je pense que cet exemple (1) serait bien même dans ce cas. – JoelFan

-2

Si vous êtes préoccupé de limiter la durée de vie de la variable plutôt que l'élimination automatique, vous pouvez toujours le mettre dans son champ d'application:

void Foo() 
{ 
    { 
     SqlConnection con = new SqlConnection("connectionStringGoesHere"); 
     // do stuff 
     // delete it before end of scope of course! 
    } 
} 
+1

Ce ne sera ni appel le destru ctor à la fin de la portée, et "Dispose()" ne sera pas appelé. Ce sens a le même effet qu'en C#. –

+0

Oui, vous avez raison. Ça ne va pas. J'ai supposé que cela serait fait dans la partie «faire les choses». Tout ce que je soulignais est que con ne peut pas être accessible en dehors de cette nouvelle portée. –

4

Pour que managé C++ simplement utiliser la sémantique de la pile. Lorsque con est hors de portée, le "destructeur", c'est-à-dire Dispose(), est appelé.

+0

+1, http://en.wikipedia.org/wiki/Resource_acquisition_is_initialization – orip

2

Vous pouvez faire quelque chose similaire dans un style auto_ptr:

void foo() 
{ 
    using(Foo, p, gcnew Foo()) 
    { 
     p->x = 100; 
    } 
} 

ce qui suit:

template <typename T> 
public ref class using_auto_ptr 
{ 
public: 
    using_auto_ptr(T ^p) : m_p(p),m_use(1) {} 
    ~using_auto_ptr() { delete m_p; } 
    T^ operator ->() { return m_p; } 
    int m_use; 
private: 
    T^m_p; 
}; 

#define using(CLASS,VAR,ALLOC) \ 
    for (using_auto_ptr<CLASS> VAR(ALLOC); VAR.m_use; --VAR.m_use) 

Pour référence:

public ref class Foo 
{ 
public: 
    Foo() : x(0) {} 
    ~Foo() 
    { 
    } 
    int x; 
}; 
0
#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 

} 
Questions connexes