我正在寻找一种优雅的解决方案,用于在 C++ 中实现等效于 C# using 语句。理想情况下,生成的语法应该易于使用和阅读。
C# Using 语句细节在这里 - http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
我不确定解决方案是否是在类上使用带有析构函数的函数指针,某种形式的巧妙模板编程甚至元模板编程。基本上我不知道从哪里开始......
你不需要在 C++ 中实现它,因为 RAII 的标准模式已经满足了你的需要。
{
ofstream myfile;
myfile.open("hello.txt");
myfile << "Hello\n";
}
当块作用域结束时,
myfile
被销毁,关闭文件并释放与对象关联的所有资源。
using
语句存在于 C# 中的原因是为 try/finally 和 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.
有关 std::auto_ptr<> 的更多信息,请参见http://en.wikipedia.org/wiki/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”语句发生冲突,后者显然具有不同的含义。
#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
首先,我们必须定义一个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.
}
作为强调 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.