Jon*_*age 10 destructor c++-cli
如果我编译并运行以下代码:
using namespace System;
ref class C1
{
public:
C1()
{
Console::WriteLine(L"Creating C1");
}
protected:
~C1()
{
Console::WriteLine(L"Destroying C1");
}
};
int main(array<System::String ^> ^args)
{
C1^ c1 = gcnew C1();
delete c1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...代码编译没有错误,并运行给我这个:
Creating C1
Destroying C1
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)
如果我在C++中执行相同操作,则会出现以下错误:
1>ProtectedDestructor.cpp(45): error C2248: 'C1::~C1' : cannot access protected member declared in class 'C1'
1> ProtectedDestructor.cpp(35) : compiler has generated 'C1::~C1' here
1> ProtectedDestructor.cpp(23) : see declaration of 'C1'
Run Code Online (Sandbox Code Playgroud)
...那么为什么它在CLI中有效?
Han*_*ant 14
这是一个漏洞抽象问题.C++/CLI有几个,我们已经经历了const关键字问题.在这里大致相同,运行时没有任何析构函数的概念,只有终结器是真实的.所以它必须是假的.创造这种错觉非常重要,原生C++中的RAII模式是神圣的.
它是通过在IDisposable接口顶部使用析构函数的概念来实现的.使确定性破坏在.NET中起作用的那个.很常见的是,C#语言中的using关键字例如调用它.在C++/CLI中没有这样的关键字,您使用delete运算符.就像在原生C++中一样.编译器可以帮助您在使用堆栈语义时自动发出析构函数调用.就像本机C++编译器一样.拯救RAII.
体面的抽象,但是,它泄漏了.问题是接口方法总是公开的.技术上可以通过显式接口实现将其设为私有,尽管它只是一个权宜之计:
public ref class Foo : IDisposable {
protected:
//~Foo() {}
virtual void Dispose() = IDisposable::Dispose {}
};
Run Code Online (Sandbox Code Playgroud)
当你尝试这个时,产生一个非常令人印象深刻的错误列表,编译器尽可能努力反击:).C2605是唯一相关的:"'Dispose':此方法在托管类中保留".当你这样做时,它无法维持幻觉.
简而言之,IDisposable :: Dispose()方法实现始终是公共的,无论析构函数的可访问性如何.该delete运营商调用它.没有解决方法.
除了Hans的详细解答,delete在C++/CLI对象实际上是激活IDisposable接口,接口继承总是公共1,它可能是富有成效的问题
那么受保护的析构函数如何被调用?
编译器生成的Dispose方法调用用户定义的析构函数.因为此Dispose方法是类的成员,所以它具有访问权限protected和private类成员,例如析构函数.
(在本机C++中,编译器不受可访问性规则的约束,因为它是强制执行它们的.在.NET中,IL验证器强制执行它们.)
1实际上,他的解释主要是编译器不允许显式实现IDisposable::Dispose(),在这种情况下它可能是私有成员.但这完全无关紧要. virtual可以通过声明类型联系成员.并且delete不打电话object->Dispose(),它打电话safe_cast<IDisposable^>(object)->Dispose().
| 归档时间: |
|
| 查看次数: |
393 次 |
| 最近记录: |