使用语句实现C#的C++等价物

Implementing C++ equivalent of C# using statement

本文关键字:C++ 等价物 实现 语句      更新时间:2023-10-16

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

C#使用语句的详细信息如下-http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

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

您不需要在C++中实现这一点,因为RAII的标准模式已经满足了您的需求。

{
    ofstream myfile;
    myfile.open("hello.txt");
    myfile << "Hellon";
}

当块作用域结束时,myfile将被销毁,从而关闭文件并释放与对象相关联的任何资源。

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

我来看看如何使用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.

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

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

#define Using(what, body) { what; body; }
Using(int a=9,
{
    a++;
})
a++; // compile error, a has gone out of scope here

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

    #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

首先,我们必须定义一个可关闭/可丢弃的公共接口:

#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.
} 

我建议阅读以下链接:

  1. C++RAII与Java Dispose模式的比较
  2. C++、C#和Java中的构造函数异常
  3. 更多C++习语/资源获取是初始化
  4. 资源获取是初始化(RAII)

作为其他答案的替代方案,它强调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。