Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не удаётся передать this указателю на класс 
:(
    Опции темы
Proger10
Дата 9.11.2013, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Передо мной проблема: организовать классы игровых сцен. Сцены это как целый отдельный экран (меню, игровой экран, настройки, статистика - всё это сцены). Проблема в том, что сцену мне нужно менять внутри очередной сцены. Не удаётся сделать это. У меня есть класс Scene - базовый класс сцены. Есть класс SceneManager - он переключает сцены созданием нового экземпляра класса нужной сцены (и предварительным удалением прошлого, если такой был). Вот этот SceneManager мне и нужно вызвать из класса GameScene/MenuScene.

Вот что у меня сейчас получается:

Код
// -----[ main.cpp ]----- //
#include "SceneManager.h"
#include "Scene.h"

int main( int argc, const char * argv[] ) {
    SceneManager *sceneManager = new SceneManager();
    sceneManager->changeScene( 0 );
    delete sceneManager;
    return 0;   
}

// -----[ Scene.h ]----- //
class SceneManager;
class Scene {
public:
    SceneManager *sceneManager;
    void start( SceneManager *sceneManager );
};

// -----[ SceneManager.h ]----- //
#include "Scene.h"
#include "MenuScene.h"
#include "GameScene.h"

class Scene;
class MenuScene;
class GameScene;

class SceneManager {
public:
    Scene* scene;

    void changeScene( short id ) {

        if ( scene != NULL ) {
            delete scene; // для предотвращения утечки памяти
        }

        if ( id == 0 ) {
            scene = new MenuScene();
        } else if ( id == 1 ) {
            scene = new GameScene();
        }

        if (scene) {
            scene->start( this );
        }
    }
};


// -----[ MenuScene.h ]----- //
class MenuScene: public Scene {
public:
    void start( SceneManager *sceneManager ) {
        this->sceneManager = sceneManager;
    }
};

// -----[ GameScene.h ]----- //
class GameScene: public Scene {
public:
    void start( SceneManager *sceneManager ) {
        this->sceneManager = sceneManager;
    }
};


Может кто знает как такую схему организовать лучше?
Проблема моя в этой ошибке компилятора (XCode 4.6, MacOS):

Код

Apple Match-O Linker (id) Error
Undefined symbols for architecture x86_64:
  "Scene::start(SceneManager*)", referenced from:
      SceneManager::changeScene(short) in main.o
ld: symbol(s) not found for architecture x86_64


Не нравится ему моя попытка передачи указателя, а по-другому и не знаю как вызвать SceneManager из внутреннего класса (GameScene, например), внутри которого экземпляр этого GameScene и создавался. Подскажите пожалуйста, что здесь можно сделать?

Это сообщение отредактировал(а) Proger10 - 9.11.2013, 21:18
PM MAIL   Вверх
volatile
Дата 9.11.2013, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Proger10 @  9.11.2013,  21:16 Найти цитируемый пост)
Undefined symbols ...  "Scene::start(SceneManager*)

линкер не нашел тела Scene::start
вам надо его добавить, либо сделать так:
Цитата(Proger10 @  9.11.2013,  21:16 Найти цитируемый пост)
class Scene {
public:
    SceneManager *sceneManager;
    virtual
    void start( SceneManager *sceneManager ) =0;
};


PM MAIL   Вверх
Proger10
Дата 9.11.2013, 21:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(volatile @ 9.11.2013,  21:30)
Цитата(Proger10 @  9.11.2013,  21:16 Найти цитируемый пост)
Undefined symbols ...  "Scene::start(SceneManager*)

линкер не нашел тела Scene::start
вам надо его добавить, либо сделать так:
Цитата(Proger10 @  9.11.2013,  21:16 Найти цитируемый пост)
class Scene {
public:
    SceneManager *sceneManager;
    virtual
    void start( SceneManager *sceneManager ) =0;
};

Работает, спасибо smile А не подскажите, как убрать предупреждение: "Delete called on 'Scene' that is abstract but has non-virtual destructor" на строчке: "delete scene;"? Я так понимаю удалить он пытается виртуальный класс, а не тот, который я создавал (MenuScene, GameScene) вызвав деструктор абстрактого класса Scene. Это ведь прямой путь к memory leak или нет? Как этого избежать в этом случае?

Это сообщение отредактировал(а) Proger10 - 9.11.2013, 22:05
PM MAIL   Вверх
volatile
Дата 9.11.2013, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Proger10 @  9.11.2013,  21:56 Найти цитируемый пост)
как убрать предупреждение: "Delete called on 'Scene' that is abstract but has non-virtual destructor" 

добавьте пустой виртуальный диструктор.


PM MAIL   Вверх
Proger10
Дата 10.11.2013, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(volatile @ 9.11.2013,  23:42)
Цитата(Proger10 @  9.11.2013,  21:56 Найти цитируемый пост)
как убрать предупреждение: "Delete called on 'Scene' that is abstract but has non-virtual destructor" 

добавьте пустой виртуальный диструктор.

А утечки памяти здесь не будет? Ведь не вызывается деструктор и не уничтожается сама тело класса MenuScene/GameScene? Или мне в этом десткрукторе надо как-то удалить то, что создано на основе классов MenuScene/GameScene?

Это сообщение отредактировал(а) Proger10 - 10.11.2013, 00:16
PM MAIL   Вверх
volatile
Дата 10.11.2013, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Proger10 @  10.11.2013,  00:07 Найти цитируемый пост)
А утечки памяти здесь не будет? Ведь не вызывается деструктор и не уничтожается сама тело класса MenuScene/GameScene? 

Как это не вызывается?
Вот для того мы и сделали деструтор виртуальным, чтобы вызывались деструкторые производных классов.
В деструкторе базового/абстрактного класса (поскольку вы ничего там не создаете) ничо удалять и не нужно.
А все что создали в производных классах, удаляйте в их-же деструкторах. Они (деструкторы) будут вызваны.


Это сообщение отредактировал(а) volatile - 10.11.2013, 01:09
PM MAIL   Вверх
Proger10
Дата 10.11.2013, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(volatile @ 10.11.2013,  00:59)
Цитата(Proger10 @  10.11.2013,  00:07 Найти цитируемый пост)
А утечки памяти здесь не будет? Ведь не вызывается деструктор и не уничтожается сама тело класса MenuScene/GameScene? 

Как это не вызывается?
Вот для того мы и сделали деструтор виртуальным, чтобы вызывались деструкторые производных классов.
В деструкторе базового/абстрактного класса (поскольку вы ничего там не создаете) ничо удалять и не нужно.
А все что создали в производных классах, удаляйте в их-же деструкторах. Они (деструкторы) будут вызваны.

Точно. Только что проверил, действительно, деструктор MenuScene также вызывается. Главное, не забыть, что в виртуальном базовом классе Scene деструктор также был витуальным. smile Спасибо ещё раз, теперь разобрался!

Кстати, а нужно ли наследуясь от виртуального класса Scene делать методы также виртуальными? Т.е. что-то типа:
Код

class MenuScene: public Scene {
public:
    virtual void start( SceneManager *sceneManager ) {
        this->sceneManager = sceneManager;
    }
    virtual ~MenuScene(){
        std::cout << "~MenuScene()\n";
    }
};


Это сообщение отредактировал(а) Proger10 - 10.11.2013, 01:35
PM MAIL   Вверх
volatile
Дата 10.11.2013, 01:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Proger10 @  10.11.2013,  01:32 Найти цитируемый пост)
 нужно ли наследуясь от виртуального класса Scene делать методы также виртуальными? Т.

По барабану, они и так по-любому уже виртуальные.
Если-же с точки стиля написания, то наверное да, наглядно видно что виртуальные.
PM MAIL   Вверх
vinter
Дата 10.11.2013, 08:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата

Кстати, а нужно ли наследуясь от виртуального класса Scene делать методы также виртуальными? Т.е. что-то типа:

При использовании современных компиляторов, реализующих C++11,  это совершенно не имеет смысла, зато имеет смысл исопльзовать override.
Код

class MenuScene: public Scene {
public:
    void start( SceneManager *sceneManager ) override{
        this->sceneManager = sceneManager;
    }
};



--------------------
Мой блог
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0487 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.