2008-12-03 17 views

Odpowiedz

31

Zakładając znaczy C++/CLI (nie stary Managed C++), są następujące opcje:

(1) naśladować używając-Block z wykorzystaniem automatycznych/stackbased obiektów:

{ 
    SqlConnection conn(connectionString); 
} 

Spowoduje to wywołanie Destruktora obiektu "conn", gdy kończy się następny zamykający blok. Niezależnie od tego, czy jest to funkcja obejmująca, czy też blok dodawany ręcznie do limitu zasięgu, nie ma znaczenia.

(2) Wyraźnie nazywamy „wyrzucić”, to znaczy zniszczeniu obiektu

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

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

Pierwszy z nich jest zamiennikiem „za”. Drugi to opcja, zazwyczaj nie musisz tego robić, chyba że opcjonalnie przekażesz odniesienie gdzie indziej.

+0

Czy pierwsza składnia (przy użyciu nieosłoniętych nawiasów klamrowych do ograniczenia zakresu) gwarantuje wywołanie Dispose, nawet jeśli opuszczasz zakres, rzucając wyjątek? Nie sądziłem, że tak jest, ale oczywiście mogę się mylić. – Coderer

+0

Tak, jest to gwarantowane. W rzeczy samej taki jest pomysł tutaj. Destruktory obiektów przydzielonych do stosu są wywoływane, gdy zamykający się zakres kończy (regularnie lub przedwcześnie przez wyjątek) - w rzeczywistości nie ma to nic wspólnego z zarządzanym lub nie. Tak samo jest w natywnym kodzie. –

+0

@ Christian.K, czy jesteś pewien "chyba, że ​​opcjonalnie przekażesz odniesienie gdzie indziej"? Myślę, że ten przykład (1) byłby w porządku nawet w takim przypadku. – JoelFan

-2

Jeżeli obawiasz się o ograniczenie żywotności zmienna, a nie automatycznego usuwania, zawsze można po prostu umieścić go w swoim zakresie:

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

To nie będzie ani wezwanie destrukcja ctor na końcu zakresu, ani nie zostanie wywołany "Dispose()". To poczucie, że ma taki sam efekt jak w C#. –

+0

Tak, masz rację. Nie będzie. Zakładałem, że zostanie to zrobione w części "zrób to". Wszystko, co wskazywałem, to to, że nie można uzyskać dostępu poza tym nowym zakresem. –

4

Aby do tego w Managed C++ po prostu użyć semantyki stos.

void Foo(){ 
    SqlConnection con("connectionStringGoesHere"); 
    //do stuff 
} 

Po wykryciu znaku krzyżyka wywoływana jest funkcja "Destruktor", tj. Usuwanie().

+0

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

2

Można zrobić coś podobny w stylu auto_ptr:

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

z następujących czynności:

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) 

Dla porównania:

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 

} 
Powiązane problemy