Здесь курят мануал.

Добро пожаловать на Пыху!

Логин:
Пароль:
 

Нет прописки? Зарегистрируйся!

Новости

Пыха переехала на новый сервер, ура!

Краснодарское время: 25 Май, 2012, 08:15:16

Страниц: [1]
Печать
Автор Тема: Вложенный файл не видит файла который был включенным раньше(?)  (Прочитано 605 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Rotten    ↓ 
06 Май, 2011, 02:23:54
НЕ ХУЕТА! ХУЕТА!

Группа: Адекваты

Карма: 9
Сообщений: 2088
Сила слова: 0.43

Такая вот ситуация. Есть несколько файлов(классов) которые инклюдятся в определенном из них по необходимости.
(Программа - на языке С++, не смотря на то что сорцы предоставленные здесь - на гарпе, т.к. варианта обернуть его в с++ я не нашел из предоставленных).
А именно...
1. Файл KeyBoard.cpp. Он инклюдится в винМэйн методе первым. Все что инклюдится дальше - то все через него(в винмэйне из этой все игрархии больше ничего нет). В этом файле все что нас интересует - это включенный Controller.cpp...
Text

#include "stdafx.h"
#include "Controller.cpp"
 

class KeyBoard{
 

public:
    KeyBoard(){
 
    };
private:
    Controller controller;
 
    void allocateButtons(){
 
        std::vector<KeyBoardChar> nums = this->controller.getNums();
   
    };
 
    LangLayout getDefaultLangLayout() {
        return this->controller.getDefaultLangLayout();
    }
};
 
 

2. Идем дальше... Файл Controller.cpp. Обращаем внимание на включенные Model.cpр и LangLayout.cpp, т.к. они играют тут ключевую роль.
Так же в этом классе упоминается класс KeyBoardChar(в нем то вся какраз и соль) который включен Model.cpp. Но на этом этапе пока все тоже ок...
Text

#include "stdafx.h"
#include "Model.cpp"
#include "LangLayout.cpp"
 

class Controller{
 

public:
    Controller(){
 
    };
 
    std::vector<KeyBoardChar> getNums()
    {
        Model *m = new Model();
        return m->NUMS_LAYOUT;
    };
 
   
    LangLayout getDefaultLangLayout() {
        return defaultLangLayout;
    };
 
private:
 
LangLayout defaultLangLayout,
            secondaryLayout,
            specialCharsLayout;
 
Model model;
 
    void allocateButtons(){
        OutputDebugString(L"allocateButtons()...");
    };
 
};
 

3. класс Model.cpp. Тут особо ничего нет, опять как и всюду, ключевой момент - последовательные инклюды.. и вот он, включенный KeyBoardChar.cpp...
Все, по сути я так понимаю дальше все включаемые файлы должны его видеть...
 
Text

#include "stdafx.h"
#include <vector>
#include "KeyBoardChar.cpp"
 

class Model{
 
public:
 
    std::vector<KeyBoardChar> NUMS_LAYOUT;// (12);
    
};
 
 

4. Вернемся к файлу Controller.cpp, так как он кроме Model.cpp содержит включение еще и LangLayout.cpp, который подключается позже.
Text

#include "stdafx.h"
#include <vector>
 
class LangLayout{
 

public:
 
    LangLayout() {
    
    };
 
    LangLayout(unsigned int aid) {
        this->setID(aid);
        //this.layout = new Vector();
    };
 
    unsigned int getID() {
        return this->id;
    };
 
    void setID(unsigned int aid) {
        this->id = aid;
    };
 

   
 

private:
 
   KeyBoardChar b;
    unsigned int id;
 
};
 

И вот в этом файле зарыта проблема так как компилятор на нем крешает. Если ему явно не объявить включение KeyBoardChar.срр(а нам и ненужно, ибо как было сказано - он включается раньше - в Model.cpp), то компилятор выдает:
C:\test1\LangLayout.cpp(58) : error C2146: syntax error : missing ';' before identifier 'b'
C:\test1\LangLayout.cpp(58) : error C2501: 'KeyBoardChar' : missing storage-class or type specifiers
C:\test1\LangLayout.cpp(58) : error C2501: 'b' : missing storage-class or type specifiers

(Там правда строчка не 58 потомучто я тут много убрал из файла закомменченого, но суть одна и та же - крешает в конце где обьявлено поле приватным "  KeyBoardChar b;")
 
А вот если я обьявлю инклюд фала KeyBoardChar.срр - то как и предполагалось, выдаст " 'KeyBoardChar' : 'class' type redefinition "...
 
В чем же проблема? Возможно нужно какието нэймспейсы поопределять чтоли. Я хэдеров кстати не юзаю(предполагаю определять методы/поля в классах сразу).
 
С++ стал учить недавно(пишу порт из другого языка), потому желательно жестко не критиковать... На то что написано в классах кроме иклюдов фактически можете не обращать внимания, так как это лишь попытки скомпилить иерархию включений на начальном этапе..
 

 
Спустя 41 секунду добавил
Алсо, я пробовал ставить #pragma once, но где бы его не ставил, все одно и тоже. Похоже не в том дело...
Суть вся в том что, какие свои классы в LangLayout.cpp я бы не вставлял(не важно, KeyBoardChar, Model, Controller) - он на них всегда матерится... а вот на свои встроенные - все пойдет на ура...
« Последнее редактирование: 06 Май, 2011, 02:23:13 от NRG » Записан

Жизнь слишком коротка чтобы тратить ее на бестолковое внимание троллям, мудакам, задротам и прочим отбросам общества...
Rotten    ↓ 
06 Май, 2011, 06:01:53 , спустя 3 часа 37 минут 59 секунд
НЕ ХУЕТА! ХУЕТА!

Группа: Адекваты

Карма: 9
Сообщений: 2088
Сила слова: 0.43

Я решил проблему, вроде как. Но мне кажется это далеко не лучшее решение.
В классе Controller.cpp где обьявлені инкльюді я добавил
Text

#define KBC 1
 

И наконец в классе LangLayout.cpp я проверяю...
Text

#ifndef KBC
#include "KeyBoardChar.cpp"
#endif
 

И учитывая то что условие ifndef KBC не выполняется(т.к. KBC == defined) то KeyBoardChar.cpp повторно не включается, а компилятор ничего против не имеет.
 
Но так объявлять часто препроцессорные переменные - дело муторное, должно быть решение пооптимальнее...
Записан

Жизнь слишком коротка чтобы тратить ее на бестолковое внимание троллям, мудакам, задротам и прочим отбросам общества...
vasa_c    ↓ 
07 Май, 2011, 04:39:58 , спустя 22 часа 38 минут 5 секунд
НЕ ХУЕТА! ХУЕТА!

Группа: в ухо

Карма: 81
Сообщений: 2459
Сила слова: 3.29

Зачем включать cpp'шные файлы? Обычно только H включают, а cpp просто линкуют после компиляции.
Записан

Rotten    ↓ 
08 Май, 2011, 02:34:24 , спустя 21 час 54 минуты 26 секунд
НЕ ХУЕТА! ХУЕТА!

Группа: Адекваты

Карма: 9
Сообщений: 2088
Сила слова: 0.43

Зачем включать cpp'шные файлы?
Затем как и всюду. Я долго работал с джавой, там нужно подключать файл, в котором объявлен тот класс который ты хочешь заюзать.
Вот и тут таким методом решил воспользоваться.
 
Пробовал кстати и хидер сделать и подключить его, но от проблемы я не избавился...
 
По сути в хидерах - нужно объявлять (но не определять) классы(в моем случае, а в большинстве  - глобальные переменные и прочее) и только в cpp файлах их определять/реализовать, насколько я понимаю.
В хидерах, в объявлениях всеравно будут присутствовать типы классов/интерфейсов(в параметрах функций либо в качестве возвращаемых методом типов) которые надо подключать в разнообразном порядке. Тоесть по сути проблема остается той же...
 
Есть класс которому нужен другой класс, вот он и его подключает. Другой клас в свою очередь юзает третий класс, и так далее.. Тоесть все по мере необходимости. Так предусмотрена архитектура.
Может в срр по-другому както..
Записан

Жизнь слишком коротка чтобы тратить ее на бестолковое внимание троллям, мудакам, задротам и прочим отбросам общества...
Rotten    ↓ 
08 Май, 2011, 02:39:56 , спустя 5 минут 32 секунды
НЕ ХУЕТА! ХУЕТА!

Группа: Адекваты

Карма: 9
Сообщений: 2088
Сила слова: 0.43

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

Жизнь слишком коротка чтобы тратить ее на бестолковое внимание троллям, мудакам, задротам и прочим отбросам общества...
Nyaah    ↓ 
09 Май, 2011, 09:31:21 , спустя 1 день 6 часов 51 минуту 25 секунд
НЕ ХУЕТА! ХУЕТА!

Группа: Джедаи

Карма: 34
Сообщений: 521
Сила слова: 6.53

В заголовочных файлах указываются объявления функций/классов, делаются дефайны, для оптимизации запихивают туда же тела инлайн функций, также указываются директивы прекомпилятора, в сурс файлах соответственно реализация функций и классов плюс в начале файла инклуд хедера для текущего сурс файла.
Для того чтобы не было ошибки редефайна класса/фукции (возникает, если сделать инклуд из разных файлов проекта), в заголовочный файл в начало либо вешают директиву
C#
#pragma once
либо обёртывают код директивами
C#
#ifndef _YOUR_CLASS_OR_LIB_NAME_
#define _YOUR_CLASS_OR_LIB_NAME_
 
// here other file content
 
#endif /* _YOUR_CLASS_OR_LIB_NAME_ */

в итоге обычно это выглыдит примерно так:
Файл TestClass.h:
C#
#ifndef _OUUE_TEST_CLASS_
#define _OUUE_TEST_CLASS_
 
namespace ouue {
 
class TestClass
{
private:
    int _id;
public:
    TestClass(int id = 0);
    TestClass(const TestClass& source);
    virtual ~TestClass()
    {};
    int getId() const;
}; /* class TestClass */
 
} /* namespace ouue */
 
#endif /* _OUUE_TEST_CLASS_ */

Файл TestClass.cpp:
C#
#include "TestClass.h"
 
namespace ouue {
 
TestClass::TestClass(int id) : _id(id)
{}
 
TestClass(const TestClass& source)
{
    _id = source.getId();
}
 
int TestClass::getId() const
{
    return _id;
}
 
} /* namespace ouue */
 
#endif /* _TEST_CLASS_ */
Если где-то нужен класс TestClass, просто в хедере пишем #include "TestClass.cpp", и все ок.
 
P.S. Можно конечно и cpp классы инклудить и в один файл все объявления запихивать, но ты и сам потом запутаешься, и другие люди потом, читая твой код, будут сильно материться, и компилятор будет возможно непонятные ошибки выдавать, и оптимизатор хз как работать.
Записан

Work, buy, consume, die
Rotten    ↓ 
09 Май, 2011, 10:10:39 , спустя 39 минут 18 секунд
НЕ ХУЕТА! ХУЕТА!

Группа: Адекваты

Карма: 9
Сообщений: 2088
Сила слова: 0.43

Nyaah, да, я вроде как сам понял: в хедерах теперь обьявлены у меня классы, интерфейсы, обьявления констант и т.д.
А клиент-файл(тоесть тот который первым создает инстансы одного из обьявленных классов которые архитектурно взаимодействуют между другими обьявленными) - должен быть срр-шным...
 
Правда я вот в хедерах не только обявления классов храню - а сразу реализацию чтобы не плодить на каждый хедер срр-шники.
 
Я кстати пробовал как ты и говорил(касательно ifdef), похоже что это и есть единственное решение.
 
Да, и кстати, у тебя в примере TestClass.cpp - закрытый endif без открытого #ifdef/ifndef...
 
Спасибо за внимание)...
Записан

Жизнь слишком коротка чтобы тратить ее на бестолковое внимание троллям, мудакам, задротам и прочим отбросам общества...
Nyaah    ↓ 
09 Май, 2011, 10:46:14 , спустя 35 минут 35 секунд
НЕ ХУЕТА! ХУЕТА!

Группа: Джедаи

Карма: 34
Сообщений: 521
Сила слова: 6.53

да пофик на ендиф, его не должно быть =)
А по поводу кода в хедерах всетаки лучшей практикой считается разделять описание и реализацию, тогда для того чтобы увидеть интерфейс класса, просто открываешь заголовочный файл и видишь его, без лишнего кода. Ещё у компиляторов есть опция, благодоря которой можно заставить все методы объявленные в хедерах сделать инлайн (-Ob2), тогда могут посыпаться баги при наследовании, использовании каллбеков и т.п. Если твою либу или код юзают в стороннем проекте, а там ленивые программисты, которые не любят писать inline где нужно, а именно используют такой подход, то будет нехорошо =)
Спустя 4 минуты 14 секунд добавил
и не единственное решение #ifndef - #endif, можно ещё #pragma once писать в начале заголовочного файла, эта директива говорит компилятору, что код файла должен включаться только раз
Записан

Work, buy, consume, die
Rotten    ↓ 
17 Июнь, 2011, 02:43:48 , спустя 38 дней 15 часов 57 минут 34 секунды
НЕ ХУЕТА! ХУЕТА!

Группа: Адекваты

Карма: 9
Сообщений: 2088
Сила слова: 0.43

Такой еще вопрос...
Зачем включать cpp'шные файлы? Обычно только H включают, а cpp просто линкуют после компиляции.
Тоесть при написании кода мы только хедеры подключаем а компилятор сам раздупляет что нужно подключить срр-шные файлы по имени файлов?
Тоесть вручную мы срр-шки не подключаем, только хедеры...
Записан

Жизнь слишком коротка чтобы тратить ее на бестолковое внимание троллям, мудакам, задротам и прочим отбросам общества...
Страниц: [1]
Печать
 

Перейти в:  

Этот топик скрыли: NRG, adw0rd, Sinkler