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

实施C++;C#using语句的等价形式 我正在寻找一个优雅的解决方案,用于实现C++中使用C语句的等价性。理想情况下,生成的语法应该易于使用和阅读,c#,c++,templates,using-statement,C#,C++,Templates,Using Statement,C#使用报表的详细信息如下- 我不确定解决方案是否是在类上使用带析构函数的函数指针,某种形式的智能模板编程,甚至元模板编程。基本上我不知道从哪里开始 > P>不需要在C++中实现这一点,因为RAIII的标准模式已经完成了您需要的。 { ofstream myfile; myfile.open("hello.txt"); myfile << "Hello\n"; } { 流文件; myfile.open(“hello.txt”); myfile我想看看如何使

C#使用报表的详细信息如下-


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

> P>不需要在C++中实现这一点,因为RAIII的标准模式已经完成了您需要的。
{
    ofstream myfile;
    myfile.open("hello.txt");
    myfile << "Hello\n";
}
{
流文件;
myfile.open(“hello.txt”);

myfile我想看看如何使用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.
{
甲级;
A.doSomething();
}//在此处退出此作用域后,将调用的析构函数
{
SomeClass*pA=新的SomeClass();
std::自动ptr pAutoA(pA);
pAutoA->doSomething();
}//此处也会调用A的析构函数,但这只是因为
//声明了一个std::auto_ptr,并在范围内为其分配了一个。

有关std::auto_ptr的更多信息,请参阅。我建议您阅读以下链接:


  • 类似于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”语句发生冲突,这显然具有不同的含义。

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

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

    我被告知RAII涵盖了这一点。正如Anthony所说,使用RAII将自动为您做到这一点,而且imho,它使代码比使用模式更干净。从我的观点来看,
    使用
    关键字只是一种平庸的补救方法,因为一开始就没有RAII。因此,您不应该试图模仿它。@Andre它有点难.我想C#编译器可以将作用域IDisposable处理为类似于RAII的,但我不确定它如何知道处理对象是否安全。当对象离开作用域时,可能会检查ref计数,如果0,则立即调用dispose?@DavidHeffernan我说的是不必使用使用作用域。很高兴知道,谢谢。大多数时候,我通常坚持Boost库……除了AutoTypTR和UnjyQu.Pt.Objor之外还有其他的,这比使用< /C> >的C>代码>要优越,而且它也与C++中的.NET对象一起工作。C++语法要好得多,因为尽管你仍然需要记住使用值语义语法:(1)您可以对每种类型使用它,无论它是否实现了
    IDisposable
    ,或者对于接口,不同的对象可以使用,也可以不使用,以及(2)它对类成员有效。我认为这不是一件更好或更坏的事情,而是你在环境中处理问题的工具。C++使用堆作为内存管理,也可以堆栈,但是它没有垃圾收集,所以这就是GGC延迟内存管理的区别,它有它自己的优势,所以应该怎么做?在这种情况下,我做什么工作?我们不是不同的运动团队,我们是处理不同技术的开发人员……我不明白这是一个公认的答案,而且通过这么多的投票,因为RAII只是一个设计负责人。如果说RAII一直负责所有事情,这不是让你自己陷于失败吗?更好的答案更类似于C#的
    using
    语句的是用法,更具体地说,正如这里的另一个答案所提到的。智能指针在分配的调用端为您实现了一个RAII包装器,与
    using
    非常类似。我喜欢这一点,因为我喜欢“using”的显式本质。至于宏本身,我喜欢它还有一个更好。
    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.
    } 
    
        #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