C ++ один заголовок несколько источников - PullRequest
10 голосов
/ 24 августа 2011

У меня большой класс Foo 1 :

class Foo {
public:
    void apples1();
    void apples2();
    void apples3();

    void oranges1();
    void oranges2();
    void oranges3();
}

Разделение класса не вариант 2 , но файл foo.cpp имеетвырос довольно большой.Существуют ли какие-либо серьезные недостатки в разработке определения класса в foo.h и разделении реализации функций на foo_apples.cpp и foo_oranges.cpp.

Целью здесь является исключительно удобочитаемость и организация для себя идругие разработчики, работающие в системе, которая включает этот класс.


1 «Большой» означает около 4000 строк, не генерируемых машиной.
2 Зачем?Ну, apples и oranges на самом деле категории алгоритмов, которые работают на графиках, но используют друг друга довольно широко.Их можно разделить, но из-за исследовательского характера работы я постоянно перестраиваю способ работы каждого алгоритма, который, как я обнаружил, для меня, не (на ранней стадии) хорошо согласуется с классическими принципами ООП.

Ответы [ 4 ]

5 голосов
/ 24 августа 2011

Существуют ли существенные недостатки в дизайне, связанные с сохранением определения класса в foo.h и разделением реализации функций на foo_apples.cpp и foo_oranges.cpp.

для выбора nits: Существуют ли существенные недостатки в дизайне, связанные с сохранением объявления класса в foo.h и разбиением определений методов на foo_apples.cpp и foo_oranges.cpp.

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

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

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

2) увеличивает сложность статической инициализации.

3) увеличивает время компиляции

альтернатива, которую я использую (кстати, многие разработчики ненавидят) в действительно больших программах, заключается в создании коллекции экспортируемых локальных заголовков . эти заголовки видны только для пакета / библиотеки. в вашем примере это можно проиллюстрировать, создав следующие заголовки: Foo.static.exported.hpp (при необходимости) + Foo.private.exported.hpp (при необходимости) + Foo.apples.exported.hpp + Foo.oranges.exported.hpp.

тогда вы бы написали Foo.cpp так:

#include "DEPENDENCIES.hpp"
#include "Foo.static.exported.hpp" /* if needed */
#include "Foo.private.exported.hpp" /* if needed */
#include "Foo.apples.exported.hpp"
#include "Foo.oranges.exported.hpp"

/* no definitions here */

Вы можете легко настроить разделение этих файлов в соответствии с вашими потребностями. если вы пишете свои программы с использованием соглашений c ++, редко возникают коллизии между огромными TU. если вы пишете как программист на C (много глобальных переменных, злоупотребление препроцессором, низкие уровни предупреждений и свободные объявления), то при таком подходе будет выявлено множество проблем, которые вы, вероятно, не захотите исправить.

4 голосов
/ 24 августа 2011

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

edit: В дополнение к этому, вы физически прокручиваете свой источник, как, например, с помощью среднего колеса мыши? Как уже упоминал кто-то еще, в IDE почти всегда можно щелкнуть правой кнопкой мыши объявление функции и перейти к определению. И даже если это не относится к вашей IDE, и вы используете блокнот или что-то еще, в минимум будет ctrl + f. Я был бы потерян без поиска и замены.

2 голосов
/ 24 августа 2011

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

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

0 голосов
/ 24 августа 2011

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

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

...