Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/47: Рейтинг темы: голосов - 47, средняя оценка - 4.60
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46

Ошибка со списком с кастомным классом

30.03.2016, 10:49. Показов 9707. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть один список с кастомным классом gameObject.

Прототип в game.h:
C++
1
extern std::list<gameObject> gameObjectList;
Объявление в game.cpp:
C++
1
std::list<gameObject> gameObjectList;
При компиляции, VS пишет следующее:
1. объявление несовместимо с "std::list<<error-type>, std::allocator<<error-type>>> gameObjectList" (объявлено в строке 16 из "c:\*****\gamedev\game2\game.h")
2. C2065 gameObject: необъявленный идентификатор
3. C2923 std::list: "gameObject" не является допустимым аргументом типа шаблон для параметра "_Ty"

Реализация класса gameObject
Кликните здесь для просмотра всего текста

gameObject.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once
 
#include "engine.h"
 
#define GAMEOBJECT_LOG_CREATED      "Created new gameObject %s."
#define GAMEOBJECT_LOG_DESTROYED    "gameObject %s destroyed."
#define GAMEOBJECT_LOG_FAIL         "gameObject %s: fail."
 
class gameObject
{
public:
    gameObject(char* _name, SDL_Texture *_texture, SDL_Rect _rect);
    ~gameObject();
 
    SDL_Rect rect;
    void update();
 
protected:
    char* name;
    SDL_Texture *texture;
};
gameObject.cpp
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
#define _CRT_SECURE_NO_WARNINGS
 
#include "gameObject.h"
 
gameObject::gameObject(char* _name, SDL_Texture *_texture, SDL_Rect _rect)
{
    if (_texture == nullptr)
    {
        char* msg;
        sprintf(msg, GAMEOBJECT_LOG_FAIL, name);
        logWrite(LOG_SIGN_ERROR, msg, ENGINE_EXITCODE_RESOURCE_NOT_FOUND, true);
    }
 
    name = _name;
    texture = _texture;
    rect = _rect;
 
    char* msg;
    sprintf(msg, GAMEOBJECT_LOG_CREATED, name);
    logWrite(LOG_SIGN_INFO, msg, LOG_NONSENSE, false);
}
 
gameObject::~gameObject()
{
    SDL_DestroyTexture(texture);
 
    char* msg;
    sprintf(msg, GAMEOBJECT_LOG_DESTROYED, name);
    logWrite(LOG_SIGN_INFO, msg, LOG_NONSENSE, false);
}
 
void gameObject::update()
{
    SDL_RenderClear(engineOutputRenderer);
    SDL_RenderCopy(engineOutputRenderer, texture, NULL, &rect);
}


Что я неправильно сделал, что компилятор так ругается? Заранее спасибо.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.03.2016, 10:49
Ответы с готовыми решениями:

Std::set с кастомным классом, как правильно перегрузить оператор < ?
Доброго времени суток, у меня имееться такой класс: class Truck { public: size_t getNumber(); Truck() =...

Ошибка при компиляции. Где ошибка? (Работа с классом)
Уважаемые форумчане! При компиляции проекта возникает ошибка &quot; undefined reference to `MeterNZiF::MeterNZiF()' &quot; на 7 строку...

Ошибка с классом
По печени не бейте больно... Но не получается разобраться в чём беда? public class Struc { public class Cat { ...

17
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
30.03.2016, 12:14
Цитата Сообщение от Chainik228 Посмотреть сообщение
C2065 gameObject: необъявленный идентификатор
Компилятор не видит определения gameObject.
Забыли #include "gameobject.h"?
Цитата Сообщение от Chainik228 Посмотреть сообщение
C++
1
2
char* msg;
sprintf(msg, GAMEOBJECT_LOG_CREATED, name);
Вы думаете тут все хорошо?
0
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 15:58  [ТС]
Цитата Сообщение от avgoor Посмотреть сообщение
Забыли #include "gameobject.h"?
Если бы. Компилятор ругается именно на ошибку инициализации gameObjectList в game.h.

Цитата Сообщение от avgoor Посмотреть сообщение
Вы думаете тут все хорошо?
А что в этом плохого?
0
 Аватар для Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
30.03.2016, 16:04
Цитата Сообщение от Chainik228 Посмотреть сообщение
Что я неправильно сделал, что компилятор так ругается?
А у вас нет копирующего конструктора (и операции =) для gameObject - что для помещения в контейнер обязательно.
0
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 16:09  [ТС]
Цитата Сообщение от Olej Посмотреть сообщение
А у вас нет копирующего конструктора (и операции =) для gameObject - что для помещения в контейнер обязательно.
А не могли снабдить примером? Пожалуйста.
0
 Аватар для Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
30.03.2016, 16:21
Это очень приблизительно (я не помню какие там есть операции копирования для SDL_Rect, SDL_Texture):
C++
1
2
3
4
5
6
7
8
9
10
11
12
gameObject::gameObject( const gameObject::gameObject& go ) {
   rect = go.rect;
   strcpy( name, go.name );
   *texture = *go.texture
}
 
gameObject::gameObject& operator =( const gameObject::gameObject& go ) {
   rect = go.rect;
   strcpy( name, go.name );
   *texture = *go.texture
   return *this;
}
Я бы вообще не выносил всё это в .cpp, а определил в .h ... но это дело вкуса.
1
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 16:51  [ТС]
Попробую. Спасибо.

Добавлено через 25 минут
Не работает. Те же ошибки.

Может проблема в коде?
game.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma once
 
#include <list>
 
#include "engine.h"
#include "log.h"
#include "gameObject.h"
 
#include "SDL2\SDL.h"
#include "SDL2\SDL_image.h"
 
#define GAME_START_CYCLE        "Start game cycle."
 
extern bool gameWork;
extern const Uint8 *gameKeyboardState;
extern std::list<gameObject> gameObjectList;
 
void gameRun();
void gameLoadResources();
game.cpp
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
#include "game.h"
 
bool gameWork = true;
const Uint8 *gameKeyboardState;
std::list<gameObject> gameObjectList;
 
/*
Run game cycle.
*/
void gameRun()
{
    gameLoadResources();
 
    logWrite(LOG_SIGN_INFO, GAME_START_CYCLE, LOG_NONSENSE, false);
    gameKeyboardState = SDL_GetKeyboardState(NULL);
    SDL_Event gameEvent;
    while (gameWork)
    {
        while (SDL_PollEvent(&gameEvent))
        {
            SDL_PumpEvents();
 
            if ((gameKeyboardState[SDL_SCANCODE_LALT]) && (gameKeyboardState[SDL_SCANCODE_F4])) gameWork = false;
 
            SDL_RenderPresent(engineOutputRenderer);
        }
    }
}
 
void gameLoadResources()
{
    SDL_Rect objPlayer_rect;
    objPlayer_rect.x = 40;
    objPlayer_rect.y = 40;
    objPlayer_rect.w = 30;
    objPlayer_rect.h = 30; 
 
    gameObject objPlayer("player", IMG_LoadTexture(engineOutputRenderer, "res/player.png"), objPlayer_rect);
    gameObjectList.push_back(objPlayer);
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,218
30.03.2016, 17:25
Цитата Сообщение от Chainik228 Посмотреть сообщение
C2065 gameObject: необъявленный идентификатор
Вы что-то не договариваете. Если ошибка врзникает именно в game.h, то возможно наличествует зацикленное включение заголовочных файлов.

Покажите, какие именно заголовочные файлы включены в game.h, gameobject.h, engine.h и т.п.
0
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 17:29  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Покажите, какие именно заголовочные файлы включены в game.h, gameobject.h, engine.h и т.п.
engine.h
C++
1
2
3
4
#include "SDL2\SDL.h"
 
#include "log.h"
#include "game.h"
log.h
C++
1
2
3
4
5
6
#include <fstream>
#include <iostream>
#include <ctime>
#include <Windows.h>
 
#include "engine.h"
game.h
C++
1
2
3
4
5
6
7
8
#include <list>
 
#include "engine.h"
#include "log.h"
#include "gameObject.h"
 
#include "SDL2\SDL.h"
#include "SDL2\SDL_image.h"
gameObject.h
C++
1
#include "engine.h"
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,218
30.03.2016, 17:39
Лучший ответ Сообщение было отмечено Chainik228 как решение

Решение

Цитата Сообщение от Chainik228 Посмотреть сообщение
engine.h
Да, проблема возникает именно из-за циклического включения заголовков: gameObject.h -> engine.h -> game.h -> gameObject.h

Последняя деталь: какой именно .cpp файл компилируется в момент возникновения ошибки и какие заголовки включены в него?
1
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 17:50  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Последняя деталь: какой именно .cpp файл компилируется в момент возникновения ошибки и какие заголовки включены в него?
Как раз gameObject.cpp.
Пойду разбираться с цикличностью. Спасибо.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,218
30.03.2016, 17:58
Цитата Сообщение от Chainik228 Посмотреть сообщение
Как раз gameObject.cpp.
Ваш gameObject.cpp сразу включает gameObject.h. Тот сразу же включает engine.h. Тот сразу же включает game.h. Тот сразу же включает gameObject.h. И тут срабатывает #pragma once. Так как мы уже включали (начали включать) gameObject.h, включение gameObject.h в этом месте игнорируется и идет дальнейшая трансляция game.h.

Разумеется, в game.h дальше получается "C2065 gameObject: необъявленный идентификатор".
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
30.03.2016, 18:02
Цитата Сообщение от Chainik228 Посмотреть сообщение
А что в этом плохого?
Писать по неинициализированному указателю хорошо?
0
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 18:06  [ТС]
Цитата Сообщение от avgoor Посмотреть сообщение
Писать по неинициализированному указателю хорошо?
Но тогда как его указать правильно?

TheCalligrapher, а если я уберу #pragma once из gameObject, то как это повлияет в дальнейшем?
0
 Аватар для Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
30.03.2016, 18:10
Цитата Сообщение от Chainik228 Посмотреть сообщение
Но тогда как его указать правильно?
Его не "указать" надо, а выделить для него место заранее ..... типа:
C++
1
char msg[ 80 ];
Цитата Сообщение от Chainik228 Посмотреть сообщение
TheCalligrapher, а если я уберу #pragma once из gameObject, то как это повлияет в дальнейшем?
Когда вы разберётесь с инклудами - вы всё раво не поместите объект без копирования в list<>.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,218
30.03.2016, 18:12
Цитата Сообщение от Chainik228 Посмотреть сообщение
а если я уберу #pragma once из gameObject, то как это повлияет в дальнейшем?
Если это единственная #pragma once в коде (и нигде нет include guards), то компилятор будет просто тупо бесконечно включать заголовочные файлы по вышеприведенному циклу до тех пор, пока не будет достигнут некий предел вложенности. После этого вылетит ошибка о чрезмерно глубоком включении заголовочных файлов.

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

Зацикленное включение заголовочных файлов - это всегда ошибка.
1
0 / 0 / 2
Регистрация: 18.10.2015
Сообщений: 46
30.03.2016, 19:18  [ТС]
Ладно. Основная проблема заключалась в зацикленности в маленькой кучке инклюдов.
Но а теперь возникла другая проблема: а как правильно организовывать их, чтобы бесконечно не включать друг друга?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,218
30.03.2016, 19:27
Цитата Сообщение от Chainik228 Посмотреть сообщение
Но а теперь возникла другая проблема: а как правильно организовывать их, чтобы бесконечно не включать друг друга?
Ну, не зная деталей вашего кода невозможно дать конкретный ответ на вопрос.

Традиционно, заголовки условно распределяются по "уровням" - от низкого уровня до высокого. Заголовкам более высокого уровня разрешается включать заголовки более низкого уровня но не наоборот.

Если у вас в программе возникает циклическая зависимость между объявлениями сущностей (типов, функций, переменных...), т.е. возникает желание устроить потенциально циклическое включение заголовка высокого уровня в заголовок низкого уровня, то вместо включения заголовка делается forward declaration проблемного типа.

Вам следует начать с условного раскладывания заголовочных файлов по уровням. После этого можно будет уже думать, где сделать включение, а где - forward declaration.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.03.2016, 19:27
Помогаю со студенческими работами здесь

Ошибка с классом.
Здравствуйте. Возникла проблема с классом. http://codepad.org/XpTrKcAC В чем может быть проблема?

Ошибка с классом в C++
#include &lt;iostream&gt; using namespace std; class Cat { public: Cat(int initAge); ~Cat(); void SetAge(int age); int...

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

Организовать связь между собственным классом и классом SpriteABC
Здравствуйте. Подскажите, пожалуйста, как можно было бы организовать связь(?) между собственным классом и классом SpriteABC? Или...

Ошибка с классом Graphics
Доброго времени суток! Не подскажите с чем может быть связана следующая ошибка: &quot;Graphics&quot; является &quot;пространство...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru