Ошибка сборки: переопределение; различные базовые типы и имя типа, впервые увиденное с использованием 'class', теперь отображается с использованием 'struct'

Я использую VS 2010 Ultimate. Набор инструментов v90.

У меня есть DLL и тестовый проект, который статически ссылается на DLL. Внутри DLL находится экспортируемый класс IFilter. Этот интерфейсный класс заключен в пространство имен, использование указанного класса явно прописано с использованием пространства имен, например. void DoSomethingWithDLLTypes (const Observer :: IFilter &);

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

C: \ Program Files \ Microsoft SDKs \ Windows \ v6.0A \ include \ Filter.h (53): предупреждение C4099: 'Observer :: IFilter': имя типа, впервые увиденное с помощью 'class', теперь отображается с 'struct' d: \ proj \ pub \ h \ IFilter.h (12): см. объявление 'Observer :: IFilter' C: \ Program Files \ Microsoft SDKs \ Windows \ v6.0A \ include \ Filter.h (183): ошибка C2371: IFilter: переопределение; различные базовые типы C: \ Program Files \ Microsoft SDK \ Windows \ v6.0A \ include \ Filter.h (53): см. объявление 'IFilter'

Первоначально IFilter не был заключен в пространство имен, поэтому мне пришлось просмотреть все мои файлы (думая, что это решит эту проблему) и обернуть все в пространство имен. Теперь DLL компилируется нормально, однако я по-прежнему получаю ту же ошибку в тестовом проекте. Я даже не знаю, как / почему включается IFilter / Filter.h из MS SDK.

В тестовом проекте используются предварительно скомпилированные заголовки, однако он не использует Windows.h, в любом случае я пошел дальше и сделал там макрос #define lean_and_mean «на всякий случай», ничего не помогло.


person clanmjc    schedule 01.08.2012    source источник
comment
IFilter - это интерфейс для подключаемых модулей службы индексирования Windows. Что-то в вашем проекте включает файл заголовка, который извлекает определение. Измените настройки проекта, чтобы выгрузить иерархию включаемых файлов во время компиляции, и посмотрите, сможете ли вы отследить ее до точки происхождения.   -  person Captain Obvlious    schedule 02.08.2012
comment
Спасибо за быстрый ответ, я попробую это и вернусь.   -  person clanmjc    schedule 02.08.2012
comment
@CaptainObvlious: в сообщении об ошибке указаны имена двух заголовков, объявляющих тип, нет необходимости сбрасывать всю иерархию (если вы не хотите знать, почему он был включен, а не что был включен)   -  person David Rodríguez - dribeas    schedule 02.08.2012
comment
@ DavidRodríguez-dribeas Знание, почему, может быть хорошей идеей на случай, если он снова столкнется с этим.   -  person Captain Obvlious    schedule 02.08.2012


Ответы (1)


Одно из мест, где компилятор Visual Studio не соответствует стандарту. В соответствии со стандартом ключевые слова struct и class могут использоваться взаимозаменяемо для объявления одного и того же типа, но VS имеет различную обработку для типов, определенных как struct и class, поэтому требуется, чтобы вы последовательно использовали одно или другое ключевое слово для вашего типа.

Теперь ошибка указывает на два, казалось бы, не связанных между собой файла заголовков, так что это может быть просто совпадение имен:

C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\Filter.h
d:\proj\pub\h\IFilter.h

В первом заголовке есть class Observer::IFilter, а во втором - struct Observer::IFilter. Если они одинаковы, то вы должны исправить проект, чтобы он не включал несколько заголовков с определением, если это разные вещи, вы должны сделать имена уникальными (добавить пространство имен)

person David Rodríguez - dribeas    schedule 01.08.2012
comment
В прошлый раз, когда я проверял, VS не требовал использовать struct и class последовательно, и это не повлияло на искажение имен. Т.е. поведение компилятора полностью соответствовало требованиям. Предупреждение в таком случае - хорошая идея, поскольку ситуация предполагает возможное непреднамеренное столкновение имен. - person AnT; 02.08.2012
comment
@AndreyT: Кажется, я припоминаю, что это было проблемой в прошлом. Я должен признать, что я не использовал VS довольно долгое время, и они могли исправить это в компиляторе (изменяя символы таким же образом) или даже в компоновщике (например, обрабатывая оба символа как псевдонимы) - person David Rodríguez - dribeas; 02.08.2012
comment
Я не могу проверить более старые версии компилятора VS, но VS2005, похоже, не имеет проблем, связанных с искажением при смешивании struct и class. Он выдает предупреждение, но, тем не менее, относится к ним одинаково. - person AnT; 02.08.2012
comment
IFilter.h, который я определил, заключен в пространство имен и является классом. Я никогда не использую «using namespace» где-либо в dll для любого пространства имен, все прописано явно. Другой заголовок, определяющий его тип как структуру, является частью Microsoft SDK. Я не понимаю, как имена совпадают с одним, заключенным в пространство имен. Окончательным исправлением было то, что мне пришлось полностью переименовать свой класс, я не знаю почему. - person clanmjc; 02.08.2012