Глава 24
А вы подумали, что есть только десять наиболее распространенных ошибок? Конечно
же, это не так! Если вы считаете себя программистом, то как и любой другой
программист — вы должны любить синтаксические ошибки. Когда я был помоложе, у нас было
около двухсот наиболее распространенных синтаксических ошибок (и все любимые).
С тех пор мало что изменилось.
Вверх
Сообщение:
error C2228: left of '.getFrobozz' must have class/struct/union type
Допустим, у одного из ваших классов есть конструктор, не требующий для себя значений аргументов:
Если вы думаете, что новый объект этого класса может быть создан следующим кодом, то вы ошибаетесь:
В действительности компилятор сразу не обнаружит ошибку. Но как только вы попытаетесь использовать новый объект, сразу же получите сообщение об ошибке. Дело в том, что компилятор интерпретирует приведенный выше код как объявление функции (их названия ведь тоже заканчиваются парой круглых скобок), которая в качества результата возвращает объект класса Doohickey.
Вверх
Признак:
Если при наборе кодов в редакторе Visual C++ активизирована возможность выделения цветом отдельных синтаксических элементов (эта возможность включена по умолчанию), вы сразу обнаружите такую ошибку, поскольку при этом целые фрагменты кодов будут окрашены не в тот цвет.
Вверх
error C2664: 'errorllf : cannot convert parameter 1 from
'char *' to 'int'
Обычно такие ошибки случаются из-за невнимательности программистов. Если, например, вы объявляете переменную одного типа, а затем пытаетесь присвоить ей значение другого типа (которое к тому же не может быть преобразовано к объявленному типу), компилятор выдаст сообщения, подобные приведенным выше. Так, следующий код содержит в себе ошибку:
Вернитесь к строке, на которую указывает компилятор, и проверьте правильность использования типов данных. Обычно такие ошибки возникают как следствие неправильного вызова функции или из-за того, что вы что-то перепутали.
Подобные ошибки будут возникать и при передаче функциям в качестве аргументов значений не тех типов, которые были для них объявлены. При этом возвращаемое сообщение об ошибке будет выглядеть приблизительно так:
error С2664: 'bar' : cannot convert parameter 1 from 'char*1 to 'int' .
Вернитесь к кодам программы и проверьте, значения каких типов передаются функции при ее вызове. Для этого вначале просмотрите коды, где эта функция объявляется, а затем посмотрите, как она вызывается.
Вверх
Вверх
Сообщения:
error C2556: 'int error12 :: b(void)' : overloaded function differs
Если функция-член объявлена как возвращающая результат типа void (пустой), но определена без использования слова void, это приведет к возникновению ошибки. Чаще такую ошибку допускают программисты, которые ранее писали программы на языке С. Сообщение об ошибке может выглядеть приблизительно так:
error C25S6: 'bar' : overloaded functions only differ by return type.
Например, такой код содержит в себе ошибку:
Функция Bummer была объявлена как возвращающая результат типа void (т.е. не возвращающая никакого результата), но определена без указания типа (компилятор по умолчанию предположит, что она возвращает результат типа int ). Таким образом, возвращение результата типа void — это не то же самое, что не указание никакого результата. Вот правильное определение функции Bummer:
Вверх
error C2871: 'System' : does not exist or is not a namespace
При написании программ .NET не забывайте использовать команду #using для подключения библиотек со стандартными функциями, которые вызываются вашей программой. В
противном случае вы столкнетесь с многими ошибками, среди которых будут, например, такие, как невозможность обнаружения чего-то, что в действительности существует.
Вверх
error C2512: 'errorl3b' : no appropriate default constructor available
Ошибка может появиться в том случае, если вы не создадите открытый конструктор для производного класса или явно не вызовете конструктор базового класса. Такие ошибки случаются редко, но, столкнувшись с ними, вы можете не сразу понять, в чем дело. Подобные проблемы возникают только при использовании возможности наследования для создания производных классов. Суть проблемы в том, что вызываемый конструктор для создания объекта производного класса не может быть найден. Возможная причина: для производного класса не был определен конструктор, вызываемый по умолчанию. Или, возможно, все конструкторы производного класса требуют передачи им значений аргументов и ни один из них не вызывается явно.
Вверх
В целом использовать команду #define для создания макроса— плохая идея, поскольку, как уже только что было сказано, сами макросы — плохие инструменты. Именно поэтому в данной книге они не рассматриваются.
Вверх
fatal error C1088: Cannot flush precompiled header file:
Довольно редко случается так, что оставшегося на диске свободного пространства становится недостаточно для решения каких-то задач, но, когда это происходит, система начинает генерировать сообщения об ошибках. Если вы получаете сообщения, подобные приведенным выше, убедитесь, что на диске по-прежнему достаточно свободного места. Если не достаточно, удалите ненужные файлы, чтобы освободить немного памяти, Или зайдите в ближайший компьютерный магазин и купите новый винчестер гигабайт этак на сорок— цены на них сейчас вполне доступные.
Вверх
Обычно реальная причина появления таких ошибок заключается в том, что были повреждены некоторые информационные файлы Visual C++. В этом случае откройте папку со своими файлами и удалите все файлы с расширением .РСН. Если это не поможет, удалите также файл с расширением .SUO (это скрытый файл), файл .VCPROJ или файл *.SLN. После этого проект должен быть создан (откомпилирован) заново, но зато теперь программа почти наверняка будет работать правильно. Можете также попробовать заново построить все исходные файлы: по одному за раз, начиная с второстепенных файлов и заканчивая тем, в котором содержится функция main.
Назад |
Начало урока |
Вверх |
Вперед
Конструкторы, которые не требуют аргументов
class Doohickey
{
int getFrobozz();
Doohickey mуDoohickey();
Чтобы компилятор понял вас правильно и создал объект, при использовании конструктора, не требующего значений аргументов, не набирайте пустую пару скобок;
Doohickey myDoohickey;
Незакрытые комментарии
Появление сообщений о самых разных ошибках.
Эту ошибку могут допускать те программисты, которые ранее писали программы на языке С и, перейдя на C++, продолжают использовать старый формат комментариев (т.е. продолжают выделять комментарии символами /* и */). Поскольку такие комментарии могут занимать несколько строк, нет ничего удивительного в том, что иногда программисты могут забывать фиксировать их окончание символами */. Последствия такой ошибки могут быть самыми непредсказуемыми. Компилятор выдаст множество сообщений об ошибках, которые, впрочем, можно будет устранить простым закрытием комментария.
По умолчанию все комментарии отображаются зеленым цветом, следовательно, при незакрытом комментарии все последующие за ним строки также будут окрашены в зеленый цвет. В этом случае вам придется просто просмотреть "зеленые" коды, найти место, где должен заканчиваться комментарий, и набрать там символы */.
Несоответствие типов данных
Сообщения:
warning C4244: '=' : conversion from 'float' to 'char',
possible loss of data
int i;
char* p = "Hello";
i = р;
Реже причиной возникновения ошибки несоответствия типов может быть использование
устаревшего заголовочного файла. Так, очень велика вероятность появления ошибки при компиляции кодов, написанных на языке С, компилятором C++. Дело в том, что язык С довольно либерален в отношении использования типов данных, в то время как C++ скрупулезно следит за соответствием типов и фиксирует все (лаже потенциальные) проблемы.
То, что работало в С, может не работать в С++
Признак:
Программа не может быть откомпилирована компилятором .
Если ваша программа была написана на языке С и прекрасно работала, но при попытке
откомпилировать ее как программу C++ вдруг возникают какие-то ошибки, вероятнее всего,
это происходит из-за несоответствия типов данных. В языке О + правильность использования типов данных отслеживается намного строже, чем в С. В девяти случаях из десяти ошибка будет относиться к одной из тех, что описаны в разделе "Несоответствие типов данных".
Использование ключевого слова void
only by return type from 'void error!2::b(void)'
error C2371: ' errorl2 :: b ': redefinition; different basic types
class foo
{
foo::Bummer()
{
void foo::Bummer()
{}
Неподключенные библиотеки функций
Сообщение:
Конструкторы для производных классов
Сообщение:
Вернитесь к главе 18, чтобы получить более детальную информацию об инициализации
конструкторов и создании конструкторов, используемых по умолчанию.
Точка с запятой в конце инструкции #define
Признак:
Возникновение самых разных ошибок.
Если в конце строки #define вы поставите точку с запятой, это приведет к появлению самых непредсказуемых проблем. Это одна из наиболее неприятных ошибок, так как компилятор при этом будет указывать на ошибки в строках, набранных где-то посреди кодов программы, хотя сами эти строки в действительности будут вполне корректны. Если где-то среди строк, на которые указывает компилятор, используется макрос (вообще говоря, это плохой инструмент),
вполне возможно, что проблема именно в нем. Проверьте, правильно ли вы набрали коды, которыми этот макрос определяется, и поставили ли вы в конце этих кодов точку с запятой.
Отсутствие свободного места на диске
Сообщения:
1WinDebug/NOHANDS.pen': No space lefc on device
fatal error C1088 : Cannot flush compiler
intermediate file: '': No space left on device
fatal error CI033: cannot open program database
1d:\project\debug\vc7 0.pdb'
error LNK1104: cannot open file "FOO.exG"
Так в чем же проблема ?
Признак:
Сообщения об ошибках указывают на корректно набранные строки.
Если будут повреждены некоторые ключевые файлы Visual C++ .NET, это может привести к появлению необъяснимых синтаксических ошибок. Например, может случиться так, что программа работала правильно, но, когда вы вернулись к ней на следующий день, она почему-то уже не компилируется. Или какая-то вполне безобидная и простая программа вдруг выдает ошибку с сообщением наподобие missing ; in stdio.h. Хотя вы точно знаете, что
эта программа не имеет никакого отношения к файлу stdio.h (или к windows.h, или к любому другому файлу, который не является частью ваших исходных кодов).
Содержание