#c
#c
Вопрос:
У меня есть класс imgmanager, который позволяет мне загружать все мои изображения ровно один раз, это довольно приятно, и во время создания прототипа у меня были все мои файлы в одном месте, поэтому мне не нужно было беспокоиться о циклических определениях. Однако после разделения всех моих классов у меня возникла проблема.
Мой заголовочный файл
#ifndef IMAGEMANAGER_H
#define IMAGEMANAGER_H
#include "Img.h"
#include <vector>
#include <map>
#include <string>
class imgmanager{
protected:
std::vector<sf::Image*> images;
std::map<std::string,int> positions;
public:
sf::Image* addimg(std::string path); //relative to resources
sf::Image* getimg(std::string path);
int size();
virtual ~imgmanager();
sf::Image* operator[](int);
}imagemgr;
#endif
С экземпляром, созданным после } и перед ; мой компилятор жалуется на меня:
Итак, я спрашиваю: что я должен сделать, чтобы иметь глобальный экземпляр моего класса imagemgr? Должен ли я просто создать глобальный заголовочный файл и создать экземпляр? (в этом конкретном случае я могу просто создать глобальную переменную в моем main.cpp ни для одного из заголовков не требуется экземпляр)
Комментарии:
1. Какая часть этого специфична для Windows или для Code::Blocks?
Ответ №1:
Не создавайте экземпляры объектов в заголовках.
Создайте экземпляр вашего объекта в одном исходном файле.
Если вам нужно получить к нему доступ через несколько единиц перевода, поместите это в свой заголовок:
extern imgmanager imagemgr; // declaration
Это сообщит всему коду, который может «видеть» заголовок, что существует так называемый объект; но он все равно будет фактически определен только в одном исходном файле, где вы написали:
imgmanager imagemgr; // definition
(Это аналогично способу, которым вы объявляете функции в заголовке, но определяете их только в одном исходном файле:
void f(); // declaration
void f() { ... } // definition
)
Приведенный выше общий совет, который я послушно передал, теперь я бы поставил под сомнение целесообразность наличия класса вообще, если вы собираетесь использовать только один его глобальный экземпляр. Либо сделайте его «одноэлементным» классом, либо используйте вместо этого свободные функции в пространстве имен.
Комментарии:
1. Томалак, я подвергаю сомнению твой последний абзац. Во-первых, Singleton является классом, поэтому «вам не нужен класс — используйте Singleton» звучит странно. Что касается использования бесплатных функций — что со всеми данными, которые должен поддерживать менеджер изображений? Это приводит к использованию статических переменных. Я не уверен, что статические переменные и свободные функции — лучший дизайн, чем singleton
2. Что ж, спасибо, Томалак, это на самом деле довольно четко указывает именно то, что я ожидал от этого случая (не зная реализации)
3. @davka: Я сказал, что сомневаюсь в обоснованности наличия класса. Я бы также поставил под сомнение целесообразность использования синглтона, который, да, все еще является классом. Но это, по крайней мере, промежуточный выход из ситуации. 🙂
Ответ №2:
Если вам требуется один глобальный экземпляр, я предлагаю вам сделать ImageManager «одноэлементным». Я не уверен, что делать для сложных типов, но для глобального объявления простого типа данных вы должны объявить переменную «extern» в заголовке и создать ее экземпляр ровно в одном модуле (cpp-файле).
Комментарии:
1. Как я и ожидал, у меня не было сомнений.
2.
extern
подходит для любого типа.