首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么不保护C++-Cli析构函数会导致编译错误?

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

Stack Overflow用户
提问于 2015-04-13 10:38:42
回答 1查看 474关注 0票数 10

如果我编译并运行以下内容:

代码语言:javascript
复制
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;
}

...the代码编译时没有错误,并运行给我以下内容:

代码语言:javascript
复制
Creating C1
Destroying C1
Press any key to continue . . .

如果我在C++中做了同样的事情,我会得到一个错误,如下所示:

代码语言:javascript
复制
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'

...so为什么它在CLI中有效?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-13 14:01:42

这是一个漏洞百出的抽象问题。C++/CLI中有几个,我们已经经历了const关键字问题。在这里,运行时没有任何析构函数的概念,只有终结器是真实的。所以它必须是伪造的。创建这种错觉非常重要,本地C++中的RAII模式是神圣的。

它是通过在IDisposable接口上插入析构函数的概念来伪造的。使确定性破坏在.NET中工作的方法。非常常见的是,C#语言中的using关键字会调用它。在C++/CLI中没有这样的关键字,您可以使用delete操作符。就像在本地C++中一样。编译器也会提供帮助,在使用堆栈语义时会自动发出析构函数调用。就像原生C++编译器所做的那样。救RAII。

不错的抽象概念,但是的,它泄露了。问题是接口方法总是公开的。从技术上讲,通过显式接口实现使其成为私有是可能的,尽管它只是一种权宜之计:

代码语言:javascript
复制
public ref class Foo : IDisposable {
protected:
    //~Foo() {}
    virtual void Dispose() = IDisposable::Dispose {}
};

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

长话短说,IDisposable::Dispose()方法实现总是公开的,而不管析构函数的可访问性如何。delete操作符调用它。解决不了这个问题。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29603291

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档