Следующее, кажется, является шаблоном, используемым 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 ++ достаточно, чтобы иметь глубокое понимание того, что вы можете и не можете с ними делать. Я надеюсь, что кто-то более знающий может пролить свет на это.
Я не уверен на 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;
Должно сработать
Вы использовали идентификатор, который начинается с подчеркивания, а затем с заглавной буквы. Эти имена зарезервированы для реализации, и использование их в пользовательском коде является неопределенным поведением.