Подтвердить что ты не робот

Предупреждение C4099: имя типа, впервые увиденное с использованием "класса", которое теперь видно с помощью "struct" (MS VS 2k8)

Это предупреждение о чем-то беспокоиться? Я читал, что это может вызвать неустойчивое поведение?

Это пример, который я пытаюсь скомпилировать, может кто-нибудь объяснить мне, почему автор объявляет объект как класс, но затем навязывает его структуре? Это нормально, если класс POD?

Спасибо.

4b9b3361

Ответ 1

Это предупреждение появляется, когда у вас есть одно объявление типа, которое противоречит другому (один говорит "класс", другой говорит "struct" ). С учетом одного правила определения все объявления, за исключением, по крайней мере, одного, должны быть передовыми объявлениями. Предупреждение, как правило, указывает на то, что декларация типа типа не соответствует действительности и обычно является простой опечаткой и должна быть исправлена. В этом случае побочных эффектов не должно быть, но вы действительно должны это исправить.

Однако могут возникнуть некоторые неприятные вещи, если у вас возникли столкновения имен типов (возможно, вызванные использованием "использования пространства имен" или глобального загрязнения пространства имен). Эти предупреждения могут указывать на то, что вы смешиваете заголовки из двух разных библиотек, а имена типов имеют столкновения. Код, составленный в этих условиях, может сделать некоторые очень неожиданные вещи.

Мой совет - понять, почему появилось предупреждение и исправить его. Если предупреждение находится в стороннем продукте, настаивайте на том, чтобы они исправили его.

Ответ 2

Просто чтобы донести комментарий MSalters от этого выше, на верхний уровень. У меня было несколько трудно найти ошибки компоновщика в результате VC, используя ключевое слово "class" или "struct" при его изменении имен.

Если вы не ожидаете, что это будет проблемой, вы можете долгое время царапать голову!

Ответ 3

Ричард Корден прав: есть причина, по которой MS предупреждает об этом. Для компилятора MS декорированные (искаженные) имена включают ключ-класс (struct или class), используемый для объявления типа. Если функция, которая принимает некоторый объект в качестве аргумента или возвращает этот объект, ссылается где-то, когда виден неправильный ключ класса, вы не получите ошибку компилятора, но компоновщик будет жаловаться, потому что оформленные имена различаются. Ошибка компоновщика показывает только тот символ, который он ищет, и здесь легко не заметить несоответствие ключа класса, поэтому более раннее, более подробное предупреждение компилятора является ценным. Конечно, возможно, что две версии не появятся в одном и том же модуле компиляции, и вы, возможно, некоторое время будете чесать голову, если считаете, что единственное отличие - это видимость элемента по умолчанию.

Разница в искажениях противоречит стандарту C++, в котором говорится, что предварительные объявления, такие как struct Foo; и class Foo; эквивалентны, и поэтому должны использовать тот же каландрирование.

Ответ 4

Я подробно обсуждаю это предупреждение в своем блоге " Действительно ли C4099 глуповат?" . Я пришел к выводу, что его лучше всего отключить.:-) Ну, по крайней мере для меня.

Ответ 5

Хотя это считается плохой практикой, я думаю, что не должно быть проблем с смешиванием класса и объявлением структуры, поскольку они представляют собой в основном один и тот же тип данных. Основное отличие состоит в том, что члены структуры по умолчанию являются общедоступными, в отличие от членов класса, которые являются частными, но в противном случае макет памяти идентичен.

Ответ 6

Одна вещь, которую я видел, которая может вызвать это предупреждение, пытается #import.tlb файл из DLL, а также иметь одну и ту же DLL в качестве ссылки в вашем проекте. Я просто исправил проблему с этим, удалив DLL в качестве ссылки из моего проекта.

Ответ 7

В c++ единственное различие между классом и структурой состоит в том, что переменные-члены класса, функции-члены и базовые классы по умолчанию являются закрытыми, а в структуре они по умолчанию являются открытыми; поэтому тот факт, что класс является POD, не должен иметь здесь никакого значения.
Я полагаю, что это предупреждение исходит от обслуживания кода (определение обновляется где-то, но не где-то еще), и исправляю код так, чтобы предупреждение исчезало (например, с использованием класса в typedef).