VS2015 Update 1 错误,或糟糕的 C++:为什么朋友 class 无法访问其朋友的受保护析构函数?

VS2015 Update 1 bug, or bad C++: Why can't a friend class access its friend's protected destructor?

以下似乎是 ZeroC ICE 在其自动生成的代码中采用的一种模式,在我看来,这似乎是他们现在为他们的工具的许多版本制作单身人士(不确定为什么)的一种方式。各种编译器都没有问题,直到今天发现Visual Studio 2015 Update 1 (VS version 14.0.24720.00, VC++ version 19.00.23506) 报错。在Update 1之前,VS2015也没有问题。我不确定它是带有 Update 1 的 VS2015 C++ 编译器中的错误(回归?),还是其他编译器放任自流的错误(不符合标准)C++ 代码。

代码模式示例如下:

class Foo {
protected:
    virtual ~Foo() {}

    friend class Foo_init;
};

class Foo_init {
public:
    Foo init;
};

static Foo_init staticFooInit;

VS2015 更新 1 发出这些错误:

example.cpp(13): error C2248: 'Foo::~Foo': cannot access protected member declared in class 'Foo'
example.cpp(3): note: see declaration of 'Foo::~Foo'
example.cpp(1): note: see declaration of 'Foo'

我找到了一个(尚未回答)ZeroC ICE forum post,它似乎与此相关,但除此之外,我在 Google 搜索中没有发现任何让我相信这是否是编译器问题的东西或错误的代码。我承认我对 ZeroC ICE 不是很了解,我也没有使用 C++ 朋友 类 来深入了解你可以用它们做什么,不能用它们做什么。我希望更有知识的人可以对此有所了解。

您使用了以下划线开头然后是大写字母的标识符。这些名称保留用于实现,在用户代码中使用它们是未定义的行为。

我不是 100% 确定你的确切问题,但这让我想起了我之前遇到的一个问题,前向声明的 classes 会有一个意想不到的范围。此页面 cppreference class 强调规则,前向声明 class 具有最局部范围。但是,您在我的 VS2015u3 上的示例也没有失败。

我认为解决方法可能是在 class 之前转发声明作为朋友的 class,以便它具有明确定义的范围。

当你有 class 例如

class Example {
     int someFunction( class SomeOtherClass & param );
};

编译器处理在本地范围内的 SomeOtherClass 声明。

这意味着

class Example {
     int someFunction( class SomeOtherClass & param );
};

class SomeOtherClass {
          ...
};

声明三个 classes Example Example::SomeOtherClassSomeOtherClass

将您的示例更改为

class Foo_init;

class Foo {
  protected:
    virtual ~Foo() {}

    friend Foo_init;
 };

class Foo_init {
  public:
    Foo init;
 };

 static Foo_init staticFooInit;

应该可以