Простой пример:
class PublicInterface {}; // e.g. GSM driver with 'send_sms'
extern PublicInterface theThing; // for most of the code (in common header)
class PrivateImplementation : public PublicInterface {}; // implementation not all need to know about
PrivateImplementation theThing; // the one and only GSM driver with all it needs to work
Не компилируется, жалуется, что PrivateImplementation theThing
конфликтует с extern PublicInterface theThing
. ОК, у меня есть другие варианты, такие как глобальный указатель (extern PublicInterface *publicThing
), который может использовать большая часть другого кода (и я установил его на publicThing = &theThing
где-то во время инициализации). Я также могу обернуть все это в пространство имен вместо класса (устройство никогда не будет иметь два модуля GSM), или Я могу поиграть, чтобы отключить extern PublicInterface theThing
для источника с реализацией (и любой другой, который можетхотите получить доступ к чему-то более конкретному - вместо этого есть extern PrivateImplementation theThing
), и это даже работает.
Вопрос: почему тогда возникает ошибка? Это просто работает, когда яимеют extern PublicInterface theThing
в некоторых источниках, extern PrivateImplementation theThing
в других источниках и PrivateImplementation theThing;
только в одном (IAR EWARM - для ATSAM4L).
Возможные проблемы, о которых я могу подумать:
Виртуальные методы (в производном, но не в базовом классе) или множественное наследование (базовое является вторым в производном). Небольшая техническая проблема, но решаемая: компоновщик должен знать, под каким типом он был указан, чтобы ввести правильный адрес - может быть другим (немного выше) для публичного доступа, который фактически живет внутри производного (после vmt или первого базового класса),Компилятор может работать с указателем (легко преобразовать указатель в производное в указатель на базу в этом publicThing = &theThing
), поэтому он может (теоретически) сделать это для глобальной переменной - разрешимый.
Скрытие метода (которое может включать явный вызов деструктора). Не проблема, потому что мы говорим в объявлении, что мы хотим видеть и использовать (выигрывает последнее объявление).
Правила, изменения которых разрешены - нельзя объявить это int
один раз иdouble
во второй раз, или он должен хотя бы предупредить.
Есть ли реальные проблемы? (Я имею в виду что-то неразрешимое.)
Что может пойти не так? (например, когда я разыгрываю трюк, чтобы использовать extern Public...
в некоторых и extern Private...
в других источниках, но не в обоих одновременно, никогда не вызывая конфликт, получая что-то, что работает должным образом.)
EDIT - Responseна некоторые комментарии:
Итак, вы в основном указываете мне на Одно определение правила . Это хотя бы частичный ответ на мои вопросы (да, придерживайтесь указателя - publicThing
, не играйте в шутки). На самом деле не отвечает на вопрос почему , но пример в самой ссылке показывает, какие проблемы он может вызвать в компиляторе (не видеть, что CDummy
- это две разные вещи в двух разных источниках). Также удача , что я не вызвал первую проблему (множественное наследование), которую я сам упомянул. Все еще не отвечая на почему , но это может быть слишком концептуально для переполнения стека, верно?