Форум программистов, компьютерный форум CyberForum.ru

Сложности с построением многофайлового решения - C++

Восстановить пароль Регистрация
 
 
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 20:33     Сложности с построением многофайлового решения #1
Есть 3-и класса. Каждый в файле. Не смотрите что реализация в h-ке, это просто чтобы было проще и удобнее понимать. Ошибка построения в итоге такая же, если даже разделить объявление и определение. Все это дело не строиться. Лучше приведу код.

SubscribersList
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
 
#include "SystemBase.h"
#include "Entity.h"
 
namespace Engine {
 
    class SubscribersList {
        friend SystemBase;
 
    public:
        SubscribersList() { }
 
        void f(Entity* e) { }
    };
}
Entity.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
 
#include "SystemBase.h"
 
namespace Engine {
 
    class Entity {
    public:
        Entity() { }
 
        void s(SystemBase* sb) { }
    };
 
}
SystemBase
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once
#include "SubscribersList.h"
#include "Entity.h"
 
namespace Engine {
 
    class SystemBase {
    public:
        SystemBase() { }
 
        void g(Entity* e) { }
 
    private:
        SubscribersList m;
 
    };
}
Некоторые условия изменения кода если кто будет менять. После friend слово class не ставить, ибо он уже был описан и подключен соответствующим файлом. Должно работать так. Если убрать все упоминания про Entity, то как раз так и работает.
Это все билдится если
1 Затолкать в один файл.
2 Перед неопределенными для компилятора типами (Entity, SystemBase) поставить class. Однако все потом опять валится как только пытаешься вынести реализацию в cpp.
VS 2010.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.03.2014, 20:33     Сложности с построением многофайлового решения
Посмотрите здесь:

Сложности с кодом C++
C++ создание многофайлового проекта в Borland 5.02
Метод вращений с построением КЮЭР-разложения C++
совсем запуталась с построением( C++
Сборка многофайлового приложения: ошибка LNK2005 C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2014, 20:57     Сложности с построением многофайлового решения #2
В классе, где есть указатель на другой класс, не нужно инклуд делать с этим классом, достаточно написать (например):
C++
1
class Entity;
ValeryS
Модератор
6373 / 4839 / 440
Регистрация: 14.02.2011
Сообщений: 16,038
26.03.2014, 21:02     Сложности с построением многофайлового решения #3
Цитата Сообщение от Rengen Посмотреть сообщение
Перед неопределенными для компилятора типами (Entity, SystemBase) поставить class. Однако все потом опять валится как только пытаешься вынести реализацию в cpp.
а как ты добавляешь файлы в проект?
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 21:38  [ТС]     Сложности с построением многофайлового решения #4
Цитата Сообщение от alsav22 Посмотреть сообщение
В классе, где есть указатель на другой класс, не нужно инклуд делать с этим классом, достаточно написать (например):
Код C++
1
class Entity;
Да. Я знаю. Я это вторым пуктом написал как сбилдить. Но хочется решить эту проблему иначе. Без использования слова class, но зато инклюдом его описания.

Добавлено через 1 минуту
Цитата Сообщение от ValeryS Посмотреть сообщение
а как ты добавляешь файлы в проект?
Правая кнопка на проекте -> Добавить -> Создать элемент. Ну или если уже существует Добавить существующий элемент.

Добавлено через 6 минут
Что-то я сглупил и не вывесил отчет компиляции. Хотя он ничего внятного в этих случаях не говорит.

1> main.cpp
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\entity.h(11): error C2061: синтаксическая ошибка: идентификатор "SystemBase"
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\subscriberslist.h(9): error C2433: Engine::SystemBase: "friend" не разрешается для объявлений данных
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\subscriberslist.h(9): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\main.cpp(10): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "b"
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\main.cpp(10): error C2065: b: необъявленный идентификатор
1> Entity.h
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\entity.h(11): error C2061: синтаксическая ошибка: идентификатор "SystemBase"
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\subscriberslist.h(9): error C2433: Engine::SystemBase: "friend" не разрешается для объявлений данных
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\subscriberslist.h(9): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\entity.h(7): error C2011: Engine::Entity: переопределение типа "class"
1> f:\my\projects 3ds, autocad and other\c++\eeee2\eeee2\entity.h(7): см. объявление "Engine::Entity"

И тогда main чтобы избавится от ищите в main.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
 
 
#include "SystemBase.h"
using namespace Engine;
 
int main()
{
    SystemBase b;
    cin.get();
    return 0;
}
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2014, 21:48     Сложности с построением многофайлового решения #5
Цитата Сообщение от Rengen Посмотреть сообщение
Но хочется решить эту проблему иначе.
Хотеть, конечно, можно... Но зачем иначе? Чем предложенный способ не устраивает?
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 22:11  [ТС]     Сложности с построением многофайлового решения #6
Цитата Сообщение от alsav22 Посмотреть сообщение
Хотеть, конечно, можно... Но зачем иначе? Чем предложенный способ не устраивает?
Действительно... Я таким способом не пользовался практически, разве что в пределах одного файла. Из-за этого я не могу полностью сейчас понять к чему приведет множество прототипов классов и 0 инклудов.
Такой способ вообще распространен? Им пользуются в больших проектах? Я просто еще нигде не видел, чтобы эту проблему решали именно так. Зачем еще раз писать прототип класса, если он есть в хедере в полном объеме? Вот. Разъясните пожалуйста.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2014, 22:19     Сложности с построением многофайлового решения #7
Цитата Сообщение от Rengen Посмотреть сообщение
Зачем еще раз писать прототип класса, если он есть в хедере в полном объеме? Вот. Разъясните пожалуйста.
А где я написал, что нужно писать и то, и то?
Цитата Сообщение от alsav22 Посмотреть сообщение
В классе, где есть указатель на другой класс, не нужно инклуд делать с этим классом, достаточно написать (например):
Касается только случая с указателем, если объект другого класса (а не указатель), то уже нужно весь хедер подключать (компилятору уже нужно будет видеть конструктор). Я не вижу всего проекта, но есть предположение, что присутствуют взаимные включения. В одном хедере подключен другой, а в том - этот. Способ с форвард-декларацией класса, как раз для таких случаев.
ValeryS
Модератор
6373 / 4839 / 440
Регистрация: 14.02.2011
Сообщений: 16,038
26.03.2014, 22:22     Сложности с построением многофайлового решения #8
Цитата Сообщение от Rengen Посмотреть сообщение
Зачем еще раз писать прототип класса, если он есть в хедере в полном объеме? Вот. Разъясните пожалуйста.
самый распространенный косяк
класс А ссылается на класс Б а класс Б ссылается на класс А подключение инклюдов ведет к рекрусивному подключению и соответственно к невозможности компиляции
вот обсуждалось
При #include "BasicObject.h" в Universe.h начинают вылезать ошибки
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 22:28  [ТС]     Сложности с построением многофайлового решения #9
Цитата Сообщение от ValeryS Посмотреть сообщение
самый распространенный косяк
класс А ссылается на класс Б а класс Б ссылается на класс А подключение инклюдов ведет к рекрусивному подключению и соответственно к невозможности компиляции
вот обсуждалось
Эту проблему решает #pragma once, которая есть.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2014, 22:30     Сложности с построением многофайлового решения #10
Цитата Сообщение от Rengen Посмотреть сообщение
Эту проблему решает #pragma once, которая есть.
В том-то и дело, что не решает.
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 22:31  [ТС]     Сложности с построением многофайлового решения #11
Цитата Сообщение от alsav22 Посмотреть сообщение
Касается только случая с указателем, если объект другого класса (а не указатель), то уже нужно весь хедер подключать (компилятору уже нужно будет видеть конструктор). Я не вижу всего проекта, но есть предположение, что присутствуют взаимные включения. В одном хедере подключен другой, а в том - этот. Способ с форвард-декларацией класса, как раз для таких случаев.
То есть использовать forward declaration? Единственный способ? Мне почему-то при написании чего-либо всегда кажется, что все должно быть еще проще, чем я делаю.

Добавлено через 57 секунд
Цитата Сообщение от alsav22 Посмотреть сообщение
В том-то и дело, что не решает.
Как нет, если да. Я специально написал два файла со взаимным включением и все отлично сбилдилось.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2014, 22:32     Сложности с построением многофайлового решения #12
Цитата Сообщение от Rengen Посмотреть сообщение
Я специально написал два файла со взаимным включением и все отлично сбилдилось.
Покажите код.
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 22:46  [ТС]     Сложности с построением многофайлового решения #13
Цитата Сообщение от alsav22 Посмотреть сообщение
Покажите код.
Я сейчас восстанавливал что писал... Перечитал что мне написали. И писал я немного не то. Я написал два включающихся файлов с классами, и два файла включались друг в друга, однако классы не ссылались друг на друга и тут я понял что был не прав. Теперь ясно.

Добавлено через 1 минуту
Теперь вопрос следующий. Это работает для случая с указателями. Что делать если внутри класса объект класса? Похоже это нельзя делать, ибо размеры класса неопределенны тогда.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.03.2014, 22:48     Сложности с построением многофайлового решения #14
Это какой, по счёту, вопрос?
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 23:01  [ТС]     Сложности с построением многофайлового решения #15
Цитата Сообщение от alsav22 Посмотреть сообщение
Это какой, по счёту, вопрос?
Лучше что они есть, чем если бы я делал проекты чужими силами за счет своих материальными средствами)
ValeryS
Модератор
6373 / 4839 / 440
Регистрация: 14.02.2011
Сообщений: 16,038
26.03.2014, 23:28     Сложности с построением многофайлового решения #16
Цитата Сообщение от Rengen Посмотреть сообщение
Теперь вопрос следующий. Это работает для случая с указателями. Что делать если внутри класса объект класса? Похоже это нельзя делать, ибо размеры класса неопределенны тогда.
не волнуйся линкер узнает
а если нужен доступ к членам то в С файле инклюде а в H class
Цитата Сообщение от Rengen Посмотреть сообщение
Эту проблему решает #pragma once, которая есть.
когда то я тоже так думал

#pragma once, влияет на одну единицу трансляции, Си файл
если не веришь проверь напиши в h файле
int a
и подключи его к нескольким С файлам

Добавлено через 14 минут
пардон фигню сморозил
для объекта нужно полное описание класса, сиречь include

но если написано так

C++
1
2
3
4
5
6
7
8
9
class A
{
 B b;
}
 
class B 
{
A a;
}
то нужно пересматривать все решение, тут include не помогут
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 23:34  [ТС]     Сложности с построением многофайлового решения #17
И у меня осталась последняя проблемка.

System.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#pragma once
#include "Mask.h"
#include "Component.h"
#include "Entity.h"
#include "SubscribersList.h"
 
#include <list>
using namespace std;
 
namespace GameEngine
{
    typedef Mask SystemMask;
    typedef Type SystemType;
 
    #define SYSTEM_HEADER(SystemName, SystemMask) \
    public: \
        static SystemMask Mask()    { static SystemMask mask((SystemMask)); return mask;} \
        static SystemType Type()    { static SystemType type(GetStaticType(#SystemName)); return type;} \
        static const char* Name()   { return #SystemName; } \
        SystemMask GetMask()        { return Mask(); } \
        SystemType GetType()        { return Type(); } \
        const char* GetName()       { return #SystemName; }
 
 
    class Entity;
    class SubscribersList;
 
    class System
    {
    public:
        virtual ~System();
    
        void Subscribe(Entity* subscriber);
        void Unsubscribe(Entity* subscriber);
        void UnsubscribeAll();
 
        virtual SystemMask GetMask() = 0;
        virtual SystemType GetType() = 0;
        virtual const char* GetName() = 0;
 
        virtual int Update(float dt) = 0;
 
    protected:
        static SystemType GetStaticType(const char* systemName);
 
    protected:
        SubscribersList m_subscribers;
    
    private:
        static TypesMapper m_SystemMap;
    };
 
}
SubscribersList.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
#include "Entity.h"
#include "System.h"
 
#include <list>
using namespace std;
 
namespace GameEngine
{
 
    class Entity;
    class System;
 
    class SubscribersList
    {
        friend System;
 
    public:
        Entity* AtFirst();
        Entity* AtLast();
        Entity* Current();
        Entity* Next();
        Entity* Prev();
 
    protected:
        void Add(Entity* subscriber);
        void Delete(Entity* subscriber);
 
    private:
        list<Entity*>::iterator m_it;
        list<Entity*>  m_subscribersList;
    };
 
}
Выдает
1>f:\my\projects 3ds, autocad and other\c++\engine\engine\system.h(47): error C2079: "GameEngine::System::m_subscribers" использует неопределенный class "GameEngine::SubscribersList"

Похоже он не ловит определение класса нигде. С этим я уже не сталкивался. В msdn ничего кроме как заменить на указатель не смогли посоветовать. В гугле что-то левое.
ValeryS
Модератор
6373 / 4839 / 440
Регистрация: 14.02.2011
Сообщений: 16,038
26.03.2014, 23:42     Сложности с построением многофайлового решения #18
Цитата Сообщение от Rengen Посмотреть сообщение
В msdn ничего кроме как заменить на указатель не смогли посоветовать.
ну так используй а в конструкторе создай по new
номер ошибки не совпадает с листитнгом, скажи на какую строчку хоть указывает?
я что то не нашел да и запутался я, честно говоря, в твоих namespace

попробуй без них сначала откомпилить
Rengen
3 / 3 / 0
Регистрация: 15.01.2012
Сообщений: 67
26.03.2014, 23:46  [ТС]     Сложности с построением многофайлового решения #19
Пишет что SubscribersList m_subscribers в System использует неопределенный class "GameEngine::SubscribersList". То есть на нее ошибка указывает.
Интересно почему теперь не видит определение SubscribersList.
А вообще, это нормальная практика чаще использовать динамическую память, агрегацию, нежели композицию? То есть, есть же случаи когда нужна композиция, но ее можно заменить и агрегацией. Что в этом случае предпочесть?

Кстати номер совпадает. Номер в первом листинге.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.03.2014, 00:16     Сложности с построением многофайлового решения
Еще ссылки по теме:

C++ Беда с наследованием. Организация многофайлового приложения
Работа многофайлового проекта C++
Компиляция и сборка многофайлового проекта C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ValeryS
Модератор
6373 / 4839 / 440
Регистрация: 14.02.2011
Сообщений: 16,038
27.03.2014, 00:16     Сложности с построением многофайлового решения #20
Цитата Сообщение от Rengen Посмотреть сообщение
вообще, это нормальная практика чаще использовать динамическую память, агрегацию, нежели композицию?
нормально
представь что у тебя класс содержит объекты других классов размером так на 100 килобайт
и создать нужно объектов этих классов штук 100
прога ляжет, стек то не резиновый, а при динамическом выделении все куче, она всяко больше
правда конструкторы копирования нужно реализовывать, память за собой чистить
в общем свои заморочки

Добавлено через 9 минут
Цитата Сообщение от Rengen Посмотреть сообщение
Кстати номер совпадает. Номер в первом листинге.
а все нашел, почему то сразу не заметил
выбрось вот эту строчку
#include "System.h" из SubscribersList.h
у тебя ведь объекта System там нет

а то смотри что получается
Цитата Сообщение от Rengen Посмотреть сообщение
System.h

C++
1
#include "SubscribersList.h"
Цитата Сообщение от Rengen Посмотреть сообщение
SubscribersList.h

C++
1
#include "System.h"
перекрестное включение, о чем мы и говорили
прагма блокирует заголовочный файл и в результате описания класса не видно
Yandex
Объявления
27.03.2014, 00:16     Сложности с построением многофайлового решения
Ответ Создать тему
Опции темы

Текущее время: 13:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru