Преобразование C источник к C++

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

41
задан Charles Stewart 20 April 2010 в 09:15
поделиться

11 ответов

Только что запустив на в значительной степени том же самом несколько месяцев назад (на десятилетнем коммерческом проекте, первоначально записанном с "C++, только C с умным struct с" философия), я предложил бы использовать ту же стратегию, которую Вы будете использовать для употребления в пищу слона: возьмите его один укус за один раз.:-)

как можно больше, разделяет его на этапы, которые могут быть сделаны с минимальными эффектами на другие части. Создание системы фасада, как Federico Ramponi предложенный, является хорошим началом - как только все имеет фасад C++ и связывается через него, можно изменить внутренности модулей со справедливой уверенностью, что они ни на что не могут влиять вне их.

Мы уже имели в распоряжении частичную систему интерфейса C++ (из-за предыдущих меньших усилий по рефакторингу), таким образом, этот подход не был трудным в нашем случае. Как только у нас было все связывающееся как объекты C++ (который занял несколько недель, работающих над абсолютно отдельным ответвлением исходного кода и интегрирующих все изменения в основном ответвлении, поскольку они были утверждены), это было очень редко, что мы не могли скомпилировать полностью рабочую версию, прежде чем мы уехали в течение дня.

переключение еще не завершено - мы приостановились дважды для временных выпусков (мы стремимся к доработанной версии каждые несколько недель), но оно уверенно двигается, и никакой клиент не жаловался ни на какие проблемы. Наши люди QA только нашли одну проблему, которую я вспоминаю, также.:-)

15
ответ дан Community 27 November 2019 в 00:49
поделиться

Что относительно:

  1. Компиляция всего в подмножестве C++ C и получают ту работу, и
  2. Реализация ряд фасады отъезд неизменного кода C?

, Почему "перевод в обязательный C++"? Можно обернуть код C без боли преобразования его в огромные классы и так далее.

12
ответ дан Federico A. Ramponi 27 November 2019 в 00:49
поделиться

Я записал бы классы C++ по интерфейсу C. Касание кода C уменьшит шанс того, чтобы портить и значительно ускорит процесс.

, Как только у Вас есть свой интерфейс C++; тогда это - тривиальная задача copy+pasting код в Ваши классы. Как Вы упомянули - во время этого шага, жизненно важно сделать поблочное тестирование.

5
ответ дан 27 November 2019 в 00:49
поделиться

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

3
ответ дан Paul Nathan 27 November 2019 в 00:49
поделиться

Давайте бросим другую глупую идею:

  1. Компиляция все в подмножестве C++ C и получают ту работу.
  2. Запускаются с модуля, преобразовывают его в огромном классе, затем в экземпляре, и создают интерфейс C (идентичный тому, который Вы запустили с) из того экземпляра. Позвольте остающемуся C кодировать работу с тем интерфейсом C.
  3. Осуществляют рефакторинг по мере необходимости, выращивание подсистемы OO из C кодирует один модуль за один раз и отбрасывает части интерфейса C, когда они становятся бесполезными.
3
ответ дан Federico A. Ramponi 27 November 2019 в 00:49
поделиться

Вероятно, две вещи рассмотреть, кроме того, как Вы хотите запуститься, включены, что Вы хотите к [1 110] фокус , и где Вы хотите к [1 111] остановка .

Вы заявляете, что существует большая маслобойка кода, это может быть ключом к фокус Ваши усилия. Я предлагаю, чтобы Вы выбрали части своего кода, где большое обслуживание необходимо, зрелые/стабильные части по-видимому рабочие достаточно хорошо, таким образом, лучше оставить их, как они, кроме, вероятно, для некоторого оформления витрины с фасадами и т.д.

, Где Вы хотите остановиться, зависит от того, что причина для желания преобразовать в C++. Это может едва быть целью сам по себе. Если это происходит из-за некоторой сторонней зависимости, сфокусируйте свои усилия на интерфейсе к тому компоненту.

программное обеспечение, я продолжаю работать, является огромной, старой кодовой базой, которая была 'преобразована' от C до C++ несколько лет назад теперь. Я думаю, что это было, потому что GUI был преобразован в QT Даже сейчас, это все еще главным образом похоже на программу C с классами. Повреждение зависимостей, вызванных общедоступными элементами данных и рефакторинг огромных классов с процедурными методами монстра в меньшие методы и классов никогда, действительно не взлетали, я думаю по следующим причинам:

  1. нет никакой потребности изменить код, который работает, и это не должно быть улучшено. Выполнение так представляет новые ошибки, не добавляя функциональность, и конечные пользователи не ценят это;
  2. Это должно очень, очень трудно чтобы сделать осуществляют рефакторинг надежно. Много частей кода являются столь большими и также настолько жизненно важными, что люди едва отваживаются касание его. У нас есть довольно обширный комплект функциональных испытаний, но достаточную информацию покрытия кода трудно получить. В результате трудно установить, существуют ли уже достаточные тесты на месте для обнаружения проблем во время рефакторинга;
  3. ROI трудно установить. Конечный пользователь не извлечет выгоду из рефакторинга, таким образом, это должно будет быть в уменьшенной стоимости обслуживания, которая увеличится первоначально, потому что путем рефакторинга Вас представляют новые ошибки в зрелом, т.е. коде довольно без ошибки. И рефакторинг себя будет дорогостоящим также...

нбар. Я предполагаю, что Вы знаете "Работу эффективно с Унаследованным кодом" книга?

3
ответ дан andreas buykx 27 November 2019 в 00:49
поделиться

Если у Вас есть маленький или академический проект (скажите, меньше чем 10 000 строк), перезапись является, вероятно, Вашим наилучшим вариантом. Можно учесть его однако, Вы хотите, и не потребуется слишком большого количества времени.

, Если бы у Вас есть реальное приложение, я предложил бы заставить его компилировать как C++ (который обычно означает, прежде всего, ремонтировать прототипов функции и т.п.), затем работайте над обертыванием OO и рефакторингом. Конечно, я не подписываюсь на философию, которые кодируют потребности быть OO, структурированным, чтобы быть приемлемым кодом C++. Я сделал бы преобразование части частью, переписав и осуществив рефакторинг, поскольку Вам нужно к (для функциональности или для слияния поблочного тестирования).

1
ответ дан Nick 27 November 2019 в 00:49
поделиться

Вот то, что я сделал бы:

  • , Так как коду 20 лет, фрагмент вниз синтаксический анализатор/синтаксический анализатор, и замените его одним из более новых lex/yacc/bison (или что-либо подобное) и т.д. базирующийся код C++, намного более удобный в сопровождении и легче понять. Быстрее для разработки также, если у Вас есть удобное BNF.
  • , Как только это модифицировано к старому коду, начните обертывать модули в классы. Замените глобальные / совместно используемые переменные интерфейсами.
  • Теперь то, что Вы имеете, будет компилятором в C++ (не совсем хотя).
  • Рисуют диаграмму классов всех классов в Вашей системе и видят, как они связываются.
  • Тянут другой с помощью тех же классов и видят, как они должны связаться.
  • Осуществляют рефакторинг код для преобразования первой схемы к второму. (это могло бы быть грязно и хитро)
  • , Не забывают использовать код C++ для всего нового добавленного кода.
  • , Если Вы имеете некоторое время в запасе, попытайтесь заменить структуры данных один за другим для использования более стандартизированного STL или Повышения.
1
ответ дан Sridhar Iyer 27 November 2019 в 00:49
поделиться

Над вашим приложением работает много людей, и их нужно не нарушать. Если вы серьезно относитесь к крупномасштабному преобразованию в объектно-ориентированный стиль, какой вам нужны инструменты массового преобразования для автоматизации работы.

Основная идея состоит в том, чтобы обозначить группы данных как классы, а затем получить инструмент для рефакторинга кода, чтобы переместить эти данные в классы, переместить функции только с этими данными в эти классы, и пересмотреть все обращения к этим данным для вызова классов.

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

Инструмент, способный выполнить эту задачу, - это наша DMS Software Reengineering. Инструментарий . DMS имеет сильные синтаксические анализаторы C для чтения вашего кода, захватывает код C. как абстрактные синтаксические деревья компилятора (и в отличие от обычного компилятора) может вычислить анализ потока для всего вашего 300 000 SLOC. У DMS есть интерфейс C ++, который можно использовать как «бэкэнд»; один пишет преобразования, которые отображают синтаксис C на синтаксис C ++.

Основная задача реинжиниринга C ++ в большой системе авионики дает некоторое представление о том, что такое использование DMS для такого рода деятельности. См. Технические документы на www.semdesigns.com/Products/DMS/DMSToolkit.html, конкретно Реинжиниринг моделей компонентов C ++ посредством автоматического преобразования программ

Этот процесс не для слабонервных. Но чем кто-либо что учитывает ручной рефакторинг большого приложения уже не боится тяжелой работы.

Да, я связан с компанией, являюсь ее главным архитектором.

7
ответ дан 27 November 2019 в 00:49
поделиться

GCC в настоящее время находится на стадии перехода на C ++ с C. Очевидно, они начали с перемещения всего в общее подмножество C и C ++. По мере того, как они это сделали, они добавили предупреждения в GCC для всего, что они нашли, в разделе -Wc ++ - compat . Это должно помочь вам в первой части вашего путешествия.

Что касается последних частей, когда у вас действительно есть все, компилируемое с помощью компилятора C ++, я бы сосредоточился на замене вещей, имеющих идиоматические аналоги на C ++. Например, если вы используете списки, карты, наборы, битовые векторы, хэш-таблицы и т. Д., Которые определены с помощью макросов C, вы, вероятно, многого добьетесь, перенеся их на C ++. Точно так же с OO вы, вероятно, найдете преимущества там, где вы уже используете идиому C OO (например, наследование структур), и где C ++ обеспечит большую ясность и лучшую проверку типов в вашем коде.

4
ответ дан 27 November 2019 в 00:49
поделиться

Вы упомянули, что ваш инструмент является компилятором, и что: «На самом деле, сопоставление с образцом, а не только сопоставление типов, при многократной отправке было бы даже лучше».

Возможно, вы захотите взгляните на maketea . Он обеспечивает сопоставление с образцом для AST, а также определение AST из абстрактной грамматики, посетителей, преобразователей и т. Д.

2
ответ дан 27 November 2019 в 00:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: