使用语句实现与 C# 等效的 C++

问题描述 投票:0回答:7

我正在寻找一种优雅的解决方案,用于在 C++ 中实现等效于 C# using 语句。理想情况下,生成的语法应该易于使用和阅读。

C# Using 语句细节在这里 - http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

我不确定解决方案是否是在类上使用带有析构函数的函数指针,某种形式的巧妙模板编程甚至元模板编程。基本上我不知道从哪里开始......

c# c++ templates using-statement
7个回答
34
投票

你不需要在 C++ 中实现它,因为 RAII 的标准模式已经满足了你的需要。

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

当块作用域结束时,

myfile
被销毁,关闭文件并释放与对象关联的所有资源。

using
语句存在于 C# 中的原因是为 try/finally 和
IDisposable
提供一些语法糖。在 C++ 中根本不需要它,因为两种语言不同,每种语言解决问题的方式也不同。


3
投票

我会看一下使用 std::auto_ptr<> 来处理在特定范围内分配和分配给指针的任何实例的清理——否则,在特定范围内声明的任何变量将在退出所述范围时简单地被破坏.

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

有关 std::auto_ptr<> 的更多信息,请参见http://en.wikipedia.org/wiki/Auto_ptr


3
投票

类似于 C# 的 using 语句的更详细的 RAII 模式可以用一个简单的宏来完成。

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

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

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

注意我们必须使用大写的“Using”以避免与 C++ 内置的“using”语句发生冲突,后者显然具有不同的含义。


3
投票
    #define USING(...) if(__VA_ARGS__; true)

        USING(int i = 0)
        USING(std::string s = "0")
        {
            Assert::IsTrue(i == 0, L"Invalid result", LINE_INFO());
            Assert::IsTrue(s == "0", L"Invalid result", LINE_INFO());
        }
        //i = 1; // error C2065: 'i': undeclared identifier
        //s = "1"; //error C2065: 's': undeclared identifier

3
投票

首先,我们必须定义一个Closeable/Disposable公共接口:

#include <iostream>

using namespace std;


class Disposable{
private:
    int disposed=0;
public:
    int notDisposed(){
        return !disposed;
    }
    
    void doDispose(){
        disposed = true;
        dispose();
    }
    
    virtual void dispose(){}
    
};

然后我们应该为using关键字定义一个宏:

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

和;这是一个示例应用程序:

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;

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");//in the scope 
    }
    
    Execute("SELECT * FROM goats");//out of the scope
    
}

但是如果你想从内存中自动删除变量,你可以简单地使用大括号

{}
;因此,范围内的每个变量都将在范围末尾被删除。 这是一个例子:

int main(int argc, const char * argv[]) {
    {
        int i=23;
    } 
    
    // the variable i has been deleted from the momery at here.
} 


0
投票

作为强调 RAII 对象的其他答案的替代方案,不需要宏并且语法与 C# 非常相似:

if(std::ofstream myfile("hello.txt"); true) {
    // code 
};

对象与花括号内的代码分开,同C#:

using (StreamReader reader = File.OpenText("hello.txt")) {
    // code 
}

像 C# 中那样的单独关键字,而不是

if
会更好,当然。

用宏,类似于C#语法:

#define Using(what) if(what; true)

Using(std::ofstream myfile("hello.txt")) {
        // code 
};

需要 C++ 17.

© www.soinside.com 2019 - 2024. All rights reserved.