Что такое управляемый C ++ эквивалент оператора C # using - PullRequest
21 голосов
/ 04 декабря 2008

Как можно написать следующий код C # в Managed C ++

void Foo()
{
    using (SqlConnection con = new SqlConnection("connectionStringGoesHere"))
    {
         //do stuff
    }
}

Clarificaton: Для управляемых объектов.

Ответы [ 5 ]

32 голосов
/ 04 декабря 2008

Предполагая, что вы имеете в виду C ++ / CLI (не старый Managed C ++), вам подойдут следующие варианты:

(1) Подражать блоку использования с использованием автоматических / основанных на стеке объектов:

{
  SqlConnection conn(connectionString);
}

Это вызовет Destructor объекта "conn", когда закончится следующий вмещающий блок. Является ли это функцией включения или блоком, который вы вручную добавляете в ограниченную область, не имеет значения.

(2) Явно вызовите «Dispose», то есть уничтожьте объект:

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

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

Первым будет прямая замена «использования». Второй вариант - вариант, который обычно не требуется, если вы не передадите ссылку куда-либо еще.

4 голосов
/ 04 декабря 2008

Для этого в Managed C ++ просто используйте семантику стека.

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

Когда con выходит из области видимости, вызывается «Destructor», т.е. Dispose ().

2 голосов
/ 23 марта 2009

Вы можете сделать что-то подобное в стиле auto_ptr:

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

со следующим:

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)

Для справки:

public ref class Foo
{
public:
    Foo() : x(0) {}
    ~Foo()
    {
    }
    int x;
};
0 голосов
/ 29 августа 2017
#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

}
0 голосов
/ 04 декабря 2008

Если вас беспокоит ограничение времени жизни переменной, а не ее автоматического удаления, вы всегда можете просто поместить ее в свою область:

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