Быстрый переход с языка C на C++ |
![]() |
Добавил(а) microsin | ||||||||||||||||||||
Итак, начальник дал Вам срочное задание перенести весь имеющийся код C на новый компилятор C++... и у Вас нет идей с чего начать, и где могут вылезти проблемы при таком портировании [1]. По большей части скомпилировать приложение C компилятором C++ не составит большого труда, потому что почти все особенности C в действительности допустимы и в коде C++, но есть несколько опасных различий, которые могут доставить Вам головную боль. Самые легкие из них те, на которые жалуется компилятор. Есть и такие, которые компилируются отлично и без нареканий, но делают совершенно разные вещи, и причину этого не всегда просто понять. [Декларации (Declarations)] Декларации в C++ (и декларации функции, и декларации типа) ведут себя по-другому, не как в C. На C++ имя класса, структуры, объединения (union) и перечисления (enumeration) автоматически представляет имя типа. Сравните следующие два варианта кода C и C++:
Обратите внимание, что строки typedef были удалены из версии C++ кода, потому что они больше не нужны. Если их все же оставить при переносе кода C на C++, то это не создаст проблемы: все скомпилируется нормально. Автоматический ввод имени, к примеру, структуры как имени типа чаще всего довольно удобно, но это может вызвать некоторые тонкие и неочевидные ошибки. Например, следующий код C будет (вероятно) рушиться, когда будет компилироваться компилятором C++:
Здесь sizeof(tone) будет 100, когда компилирование идет компилятором C и, (как минимум) 5, когда компилирование производится компилятором C++, поскольку tone дает ссылку на массив в случае языка C, но в случае C++ это будет ссылка на структуру (вообще Вы не должны давать одинаковое имя типу и переменной или полю; но это совсем другая история). В языке C функции, которые декларированы без явного указания типов аргумента могут принимать любое количество аргументов; в языке C++ это декларирует функцию, у которой нет аргументов. Также на C разрешено (но считается плохим стилем, на которое будут выдаваться варнинги) использовать функцию, которая не была перед этим задекларирована; на C++ это не разрешено.
Надлежащее использование прототипов функции позаботится обо всех этих проблемах. C также весьма прощает опускание типов переменных и типов возвращаемых из функций значений (несмотря на то, что это также считается плохим стилем), где он неявно использует int. Здесь C++ это не прощает, и требует явного декларирования типа. Например, следующий код нормально компилируется как C, но не проходит компиляцию как C++:
[Преобразование указателя (Pointer conversion)] Язык C весьма спокойно относится к неявным преобразованиям между разными типами (implicit type cast), но C++ здесь очень придирчив. В отличие от C, язык C++ использует строгую проверку типа. Типичный случай, когда Вы столкнетесь с этим, будет при компиляции такого маленького кусочка кода:
За исключением факта, что Вы должны использовать new для malloc в программах C++, вышеуказанный код не будет допустимым кодом C++. Причина в том, что неявные преобразования от типа void* к любому другому типу указателя (такому как int*) запрещены в C++. Чтобы этот код компилировался под управлением компилятора C++, используйте явное преобразование типа (explicit type cast), чтобы получить int* из void*. [Перечисления (Enumerations)] Есть подобная ситуация с константами перечисления (enumeration constants): в C разрешено неявно преобразовать данные из int в перечисляемый тип, но в C++ это запрещено. Таким образом, следующий код для C будет совершенно легальным (хотя Вы получите дружеское предупреждение), но является недопустимым кодом для C++:
Чтобы исправить ошибку, используйте явное приведение (преобразование) типа (explicit cast):
[Рекомендации по переводу кода C на C++] Следующие простые рекомендации помогут портировать Ваш код C на компилятор C++: 1. Всегда используйте стиль именования (naming convention), который делает отличие имен типов от имен полей структур и переменных. Например, используйте fruit_t, tone_t, range_t как имена типа, и используйте fruit, tone и range как имена полей или переменных. [Ссылки] 1. Instant C++ for C programmers site:iar.com (оригинал статьи на английском языке). |