ice — VS2015 Update 1 ошибка или плохой C ++: Почему класс друга не может получить доступ к защищенному деструктору друга?

Следующее, кажется, является шаблоном, используемым ZeroC ICE в коде, который он генерирует автоматически, что мне кажется способом, которым они создали синглтоны (не знаю почему) для многих выпусков своего инструмента сейчас. Различные компиляторы не имеют проблем с этим, пока сегодня я не обнаружил, что Visual Studio 2015 Update 1 (версия VS 14.0.24720.00, версия VC ++ 19.00.23506) выдает ошибку. До обновления 1 VS2015 также не было проблем с ним. Я не уверен, является ли это ошибкой (регрессией) в компиляторе C201 VS2015 с обновлением 1, или плохим (не соответствующим стандартам) кодом 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 сообщение на форуме что, похоже, связано с этим, но в остальном я не обнаружил в своем поиске в Google ничего, что убедило бы меня, является ли это проблемой компилятора или плохим кодом. Я признаю, что не очень хорошо знаю ZeroC ICE, и при этом я не использую классы друзей C ++ достаточно, чтобы иметь глубокое понимание того, что вы можете и не можете с ними делать. Я надеюсь, что кто-то более знающий может пролить свет на это.

11

Решение

Я не уверен на 100% в вашей конкретной проблеме, но она напоминает мне о проблеме, с которой я столкнулся некоторое время назад, когда классы, объявленные заранее, имели неожиданную область действия. эта страница класс cppreference выдвигает на первый план правила, что у заранее объявленного класса есть самая локальная область. Тем не менее, ваш пример на моем VS2015u3 тоже не подведет.

Я думаю, что исправление, вероятно, состоит в том, чтобы заранее объявить класс, который является другом перед классом, чтобы он имел четко определенную область видимости.

Когда у вас есть такой класс, как

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

Компилятор обрабатывает объявление SomeOtherClass который находится в локальной сфере.

Это означает, что

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

class SomeOtherClass {
...
};

Объявляет три класса Example Example::SomeOtherClass а также SomeOtherClass

Изменение вашего примера на

class Foo_init;

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

friend Foo_init;
};

class Foo_init {
public:
Foo init;
};

static Foo_init staticFooInit;

Должно сработать

1

Другие решения

Вы использовали идентификатор, который начинается с подчеркивания, а затем с заглавной буквы. Эти имена зарезервированы для реализации, и использование их в пользовательском коде является неопределенным поведением.

-6

По вопросам рекламы [email protected]