为什么受保护的 C++-Cli 析构函数不会导致编译错误?

2024-05-06

如果我编译并运行以下命令:

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

...代码编译没有错误并运行给我这个:

Creating C1
Destroying C1
Press any key to continue . . .

如果我在 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'

...那么为什么它在 CLI 中有效呢?


这是一个漏洞抽象问题。 C++/CLI 有几个,我们已经了解过const关键词问题。与此类似,运行时没有任何析构函数的概念,只有终结器是真实的。所以必须是造假的。创造这种幻觉非常重要,原生 C++ 中的 RAII 模式是神圣的。

它是通过将析构函数的概念附加到 IDisposable 接口之上来伪造的。使确定性破坏在 .NET 中发挥作用的一个。很常见的是,using例如,C# 语言中的关键字调用它。 C++/CLI 中没有这样的关键字,您使用delete操作员。就像在本机 C++ 中一样。当您使用堆栈语义时,编译器会帮助自动发出析构函数调用。就像本机 C++ 编译器一样。拯救RAII。

不错的抽象,但是,它会泄漏。问题是接口方法始终是公共的。从技术上讲,可以通过显式接口实现将其设为私有,尽管这只是权宜之计:

public ref class Foo : IDisposable {
protected:
    //~Foo() {}
    virtual void Dispose() = IDisposable::Dispose {}
};

当您尝试此操作时,会生成一个非常令人印象深刻的错误列表,编译器会尽力反击:)。 C2605 是唯一相关的:“'Dispose':此方法在托管类中保留”。当你这样做时,它无法维持幻觉。

长话短说,IDisposable::Dispose() 方法实现始终是公共的,无论析构函数的可访问性如何。这delete运算符调用它。对此没有解决方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么受保护的 C++-Cli 析构函数不会导致编译错误? 的相关文章

随机推荐