Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Разбить программу на подфайлы


Автор: lesha_od 20.12.2006, 13:12
Написал программу, и мне надо ее разбить на подфайлы. Пока что вся программа в одном файле.

Вот главная программа, к которой надо подключить функции отдельными файлами:
Код

#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
struct Elem 
{
    char surname[30];
    int year;
    double avg;
    Elem * next;
    Elem * prev;
    Elem(char * sn,int y, double a)
    {
        strcpy(surname,sn);
        year = y;
        avg = a;
        next=NULL;
        prev=NULL;
    }
    Elem()
    {
        year = 0;
        avg=0;
        strcpy(surname,"");
        next=NULL;
        prev=NULL;
    }
};
class List
{
    Elem *head;
    Elem *tail;
public:
    List():head(NULL),tail(NULL){}
    virtual ~List()
    {
        ClearAll();
    }
    void Print();
    void AddToHead(Elem *value);
    int DelSurname(const char *name);
    int HowMany();
    void DelNum(const int & position);
    void DeleteFromHead();
    void ClearAll();
    void DeleteFromTail();
    void DelElem(Elem *ptr);
    void swapitem(Elem* a,Elem* b);
    void bublesortlist();
    int DelSRight(const char *name);
    int AddLeft(const char *name, Elem * value);
};

и вот одна из функций, ее надо поместить в файл clearall.cpp
Код

void List::ClearAll()
{
    int size = HowMany();
    for (int i = 0;i<size;i++)
    {
        DeleteFromHead();
    }
}

Пробовал инклюдить по-разному, но выдается unresolved symbol и т.д.
Как сделать?

Автор: jnb 20.12.2006, 13:15
Цитата

Пробовал инклюдить по-разному, но выдается unresolved symbol и т.д.

ты наверное забыл *.срр в проект подключить

Автор: KelTron 20.12.2006, 14:04
Покажи полный код файла срр, со всеми инклудами...

Автор: Anikmar 20.12.2006, 16:04
Первый код это cpp файл? Если да - то не будет работать, когда компилится второй код компилятор не знает объявления класса List. Объявление класса надо вынести в отдельный .h файл и инклудить его.
 Можно конечно инклудить и cpp файлы, только вот вопрос зачем?

Автор: Любитель 20.12.2006, 16:40
Anikmar, только тогда их компилить не надо (инклюдимые файлы). Иначе линкер ругнётся мол "symbol .. defined in ...".

Автор: Anikmar 20.12.2006, 17:06
Цитата

Anikmar, только тогда их компилить не надо (инклюдимые файлы). Иначе линкер ругнётся мол "symbol .. defined in ...". 


Вот я и спрашиваю Зачем? Я сказал, что теоретически можно инклудить cpp файлы - это чистая правда.

Общепринятый подход:

Класс объявляется и загоняется в .h файл

Все реализации запихиваются в cpp файл (можно, конечно и в несколько - только зачем, опять таки не понимаю)

Когда реализация используется вместе с объявлением - лично я никогда это не использую (ну не нравится мне это)

И уж тем более я никогда не объявляю класс в cpp модуле - это на мой взгляд ерунда получается.

Автор: zabivator 20.12.2006, 17:11
Anikmar, некоторые классы-посредники удобней объявлять в cpp файле. Наружу тогда не торчит этот "сервисный" класс. 

Автор: Anikmar 20.12.2006, 17:15
Цитата(zabivator @ 20.12.2006,  17:11)
Anikmar, некоторые классы-посредники удобней объявлять в cpp файле. Наружу тогда не торчит этот "сервисный" класс.

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

Но это чисто мое мнение, конечно, на вкус и цвет...

Автор: zabivator 20.12.2006, 17:31
Код

class Handler
{
public:
    Handler( std::string& response ) : m_response(response) {}
    void operator()( const std::string& response )
    {
        m_response = response;
    }
private:
    std::string& m_response;
};

void nsg::console::IConsole::Synchronous( const std::string &request, std::string &response )
{
    SynchronousImplementation( request, nsg::console::ResponseHandler( Handler( response ) ) );
}

Вот пример из cppшника.

Автор: Anikmar 21.12.2006, 09:33
Цитата

Вот пример из cppшника.


Честно говоря, приведенный пример не особо впечатлил. Больше похоже на заплатку. Не могу сказать, что сходу можно посмотреть что делает nsg::console::ResponseHandler, а класс Handler - больше похож на временный наворот, предназначенный для дальнейших усовершенствований. Как только они начнут реализовываться - то либо будет создан для Handler отдельный файл либо данный код перестанет быть удобоваримый.

Автор: zabivator 21.12.2006, 11:28
Код

typedef boost::function<void ( const std::string& )> ResponseHandler;

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

Автор: Anikmar 21.12.2006, 15:38
На самом деле спор ни о чем.

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

Это мой стиль, я просто его придерживаюсь.

Автор: Любитель 22.12.2006, 16:52
Anikmar, согласен с тобой. Действительно внутренние классы предпочитаю объявлять в как вложенные в прайват.

Автор: zabivator 22.12.2006, 19:37
Anikmar, если классс понадобился где-то еще - явное указание на то, что его надо вынести в отдельный h-файл.
А если класс сужебный, и используется только в одном месте - тогда лучше в cpp, потому что его доработка не должна вызывать каскадной перекомпиляции, что будет в случае, если его объявить как private. Если же просто сделать предекларацию, то мне так не очень нравится... Ну снесу я его потом вообще, и снова будет перекомпиляция. Поскольку этот класс - детали реализации, я предпочитаю держать в его в файле с реализацией.

Автор: Anikmar 22.12.2006, 21:10
Цитата(zabivator @  22.12.2006,  19:37 Найти цитируемый пост)
Anikmar, если классс понадобился где-то еще - явное указание на то, что его надо вынести в отдельный h-файл.
А если класс сужебный, и используется только в одном месте - тогда лучше в cpp, потому что его доработка не должна вызывать каскадной перекомпиляции, что будет в случае, если его объявить как private. Если же просто сделать предекларацию, то мне так не очень нравится... Ну снесу я его потом вообще, и снова будет перекомпиляция. Поскольку этот класс - детали реализации, я предпочитаю держать в его в файле с реализацией. 


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

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

Это просто как я привык, не напрягаю никого на то, что это стандарт. Мне просто кажется это удобнее.

Автор: Любитель 23.12.2006, 15:56
Млин, развели спор по пустяковому вопросу. В принципе это дело каждого (абсолютно). Но всё-таки чем лучше класс в прайват, тем, что мы можем спокойно объявить прайват-члены этого класса (если сие нужно).
В Qt, скажем сделано соглашение, что в хейдерах идёт предобъявление класса, с суффиксом Private. В классе объявляется поле - указатель на этот класс. Других полей умногих кутешных классов почти нет. Однако, сам внутренний класс часто объявляется в отдельном хейдере, хотя инклюдится всего единожды. Ну, максимум, дважды: d обычном файле и в файле с суффиксом _p. Таким образом удаётся избежать перекомпиляции файлов, использующих наш класс, когда мы добавляем/удаляем у него поля (согласитесь, размер указателя от этого не меняется). Время компиляции без сомнения уменьшается, но... мне не нравиться такой стил. Постоянное обращение через всякие d_ptr всё же запутывает код (не то, чтобы нечитабельно, но мне не нравиться).

Автор: zabivator 23.12.2006, 17:59
Anikmar, конечно, дело вкуса.
Я мог бы его вообще локальным объявить, поскольку он только одному методу нужен.
Или локальные классы тоже зло?
Тогда курим stl.

Автор: Любитель 23.12.2006, 18:08
Цитата(zabivator @  23.12.2006,  17:59 Найти цитируемый пост)
Или локальные классы тоже зло

Не в коем случае! Но
Цитата(zabivator @  23.12.2006,  17:59 Найти цитируемый пост)
конечно, дело вкуса


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)