Каковы преимущества и недостатки разделения объявления и определения как в C++?

Вместо того чтобы писать shortVowel = [['a'], ['e'], ['y']], я написал бы shortVowel' = ['a', 'e', 'y']. Что совпадает с shortVowel' = "aey". Теперь сделайте

or [x == last $ last sentence | x <- shortVowel']

Вышеприведенное проверяет, является ли какой-либо из элементов в shortVowel последним элементом последнего слова в вашем предложении. Если вы хотите проверить все короткие гласные, сделайте

[(x, x == last $ last sentence) | x <- shortVowel']
9
задан fluffels 14 March 2009 в 11:18
поделиться

11 ответов

Исторически это должно было помочь компилятору. Необходимо было дать ему список имен, прежде чем это использовало их - было ли это фактическим использованием или предописанием (значение по умолчанию C funcion прототип в стороне).

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

Недостатки: много из в большой степени вложенного включает файлы (я проследил, включают деревья прежде, они удивительно огромны), и дублирование между объявлением и определением - все ведущие к более длительным временам кодирования, и более длительное время компиляции (когда-нибудь сравнивал время компиляции между сопоставимым C++ и проектами C#? Это - одна из причин различия). Заголовочные файлы должны быть предоставлены пользователям любых компонентов, которые Вы обеспечиваете. Возможности нарушений ODR. Уверенность в препроцессоре (многим современным языкам не нужен шаг препроцессора), который делает Ваш код более хрупким и более трудным для инструментов проанализировать.

Преимущества: нет очень. Вы могли утверждать, что добираетесь, список имен функций группировался в одном месте в целях документации - но большинство IDE имеет своего рода код, сворачивающий способность в эти дни, и проекты любого размера должны использовать генераторы документа (такие как doxygen) так или иначе. С инструментом для очистки, pre-processor-less, основанный на модуле синтаксис для инструментов легче следовать Вашему коду и обеспечить это и больше, таким образом, я думаю, что это "преимущество" примерно спорно.

14
ответ дан 4 December 2019 в 07:15
поделиться

Существует два основных преимущества для распадающегося объявления и определения в C++ заголовочные и исходные файлы. Прежде всего, Вы избегаете проблем с Одним Правилом Определения, когда Ваши class/functions/whatever #included больше чем в одном месте. Во-вторых, путем выполнения вещей этот путь, Вы разделяете интерфейс и реализацию. Пользователи Вашего класса или библиотеки должны только видеть Ваш заголовочный файл для написания кода, который использует его. Можно также сделать этот шаг дальше с Идиомой Pimpl и сделать его так, чтобы пользовательский код не перекомпилировал каждый раз изменения реализации библиотеки.

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

Другой недостаток на практике - это для записи (и отладка!) хороший код, который пользуется сторонней библиотекой, Вы обычно, должен видеть в ней. Это означает доступ к исходному коду, даже если Вы не можете изменить его. Если все, что Вы имеете, является заголовочным файлом и скомпилированным объектным файлом, может быть очень трудно решить, является ли ошибка Вашим отказом или их. Кроме того, рассмотрение источника дает Вам понимание, как правильно использовать и расширить библиотеку, которую не могла бы касаться документация. Не все поставляют MSDN с их библиотекой. И у великих разработчиков программного обеспечения есть противная привычка к выполнению вещей с Вашим кодом, что Вы никогда не мечтали возможные.;-)

3
ответ дан 4 December 2019 в 07:15
поделиться

У Вас в основном есть 2 представления о class/function/whatever:

Объявление, где Вы объявляете имя, параметры и участников (в случае структуры/класса), и определение, где Вы определяете то, что делают функции.

Среди недостатков повторение, все же одно большое преимущество состоит в том, что можно объявить функцию как int foo(float f) и оставьте детали в реализации (=definition), таким образом, любой, кто хочет использовать Ваше функциональное нечто просто, включает Ваш заголовочный файл и ссылки на Ваш library/objectfile, таким образом, пользователи библиотеки, а также компиляторы просто должны заботиться об определенном интерфейсе, который помогает пониманию интерфейсов и ускоряет время компиляции.

1
ответ дан 4 December 2019 в 07:15
поделиться

Стандарт требует, чтобы при использовании функции, объявление было в объеме. Это означает, что компилятор должен смочь проверить против прототипа (объявление в заголовочном файле), что Вы являетесь передающими к нему. Кроме, конечно, для функций, которые являются variadic - такие функции не проверяют аргументы.

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

Объявление функций в заголовке прекрасно. Но помните, объявляете ли Вы и определяете в заголовке, удостоверяются, что они встроены. Один способ достигнуть этого состоит в том, чтобы поместить определение в определении класса. Иначе предварительно ожидайте inline ключевое слово. Вы столкнетесь с нарушением ODR иначе, когда заголовок будет включен в несколько файлов реализации.

2
ответ дан 4 December 2019 в 07:15
поделиться

Это - артефакт того, как работают компиляторы C/C++.

Поскольку исходный файл компилируется, препроцессор заменяет каждым #include-statement с содержанием включенного файла. Только впоследствии делает попытку компилятора интерпретировать результат этой конкатенации.

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

Существует проблема с этим, тем не менее, когда дело доходит до вызовов взаимно рекурсивной функции:

void foo()
{
  bar();
}

void bar()
{
  foo();
}

Здесь, foo не скомпилирует как bar неизвестно. Если Вы передвигаете две функции, bar не скомпилирует как foo неизвестно.

При разделении объявления и определения, тем не менее, можно заказать функции, как Вы желаете:

void foo();
void bar();

void foo()
{
  bar();
}

void bar()
{
  foo();
}

Здесь, когда компилятор обрабатывает foo это уже знает подпись вызванной функции bar, и счастливо.

Конечно, компиляторы могли работать по-другому, но это - то, как они работают в C, C++ и к некоторому Objective C градуса.

Недостатки:

Ни один непосредственно. При использовании C/C++ так или иначе это - лучший способ сделать вещи. Если у Вас есть выбор языка/компилятора, то, возможно, можно выбрать тот, где это не проблема. Единственная вещь рассмотреть с разделением объявлений в заголовочные файлы состоит в том, чтобы избежать взаимно рекурсивного #include-statements - но это - то, что включает защиту, для.

Преимущества:

  • Скорость компиляции: Поскольку все включенные файлы связываются и затем анализируются, уменьшая сумму, и сложность кода во включенных файлах улучшит время компиляции.
  • Избегайте дублирования/встраивания кода: Если Вы полностью определите функцию в заголовочном файле, то каждый объектный файл, который включает этот заголовок и ссылается на эту функцию, будет содержать свою собственную версию той функции. Как заметка на полях, если Вы хотите встроить, необходимо поместить полное определение в заголовочный файл (на большинстве компиляторов).
  • Инкапсуляция/ясность: четко определенный класс/набор функций плюс некоторая документация должен быть достаточно, чтобы другие разработчики использовали Ваш код. Нет (идеально) никакой потребности в них понять, как код работает - итак, почему требуют, чтобы они отсеяли через него? (Контрдовод, который это, может быть полезен для них получить доступ к реализации, при необходимости все еще стоит, конечно).

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

11
ответ дан 4 December 2019 в 07:15
поделиться

Преимущество

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

0
ответ дан 4 December 2019 в 07:15
поделиться

Одно преимущество, которое я еще не видел: API

Любой код библиотеки или третьей стороны, который НЕ является открытым исходным кодом (т.е. собственный) не будет иметь их реализации наряду с распределением. Большинство компаний просто не довольно отдачей исходного кода. Легкое решение, просто распределите объявления класса и функциональные подписи, которые позволяют использование DLL.

Отказ от ответственности: Я не говорю, правильно ли это, неправильно, или выровненный по ширине, я просто говорю, что видел его много.

1
ответ дан 4 December 2019 в 07:15
поделиться

Одно большое преимущество предописаний состоит в том, что при осторожном использовании можно сократить зависимости времени компиляции между модулями.

Если ClassA.h должен относиться к элементу данных в ClassB.h, можно часто использовать просто ссылки вперед в ClassA.h и включать ClassB.h в ClassA.cc, а не в ClassA.h, таким образом сокращая зависимость времени компиляции.

Для больших систем это может сэкономить время на сборке.

0
ответ дан 4 December 2019 в 07:15
поделиться
  1. Разделение высказывает чистое, ненарушенное мнение элементов программы.
  2. Возможность создать и связаться с двоичными модулями/библиотеками, не раскрывая источники.
  3. Двоичные файлы ссылки, не перекомпилировав источники.
0
ответ дан 4 December 2019 в 07:15
поделиться

Недостаток

Это приводит к большому повторению. Большая часть функциональной подписи должна быть помещена в два или больше (как отмеченный Paulious) места.

-1
ответ дан 4 December 2019 в 07:15
поделиться

При корректном выполнении это разделение уменьшает время компиляции, когда только реализация изменилась.

0
ответ дан 4 December 2019 в 07:15
поделиться
Другие вопросы по тегам:

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