Вопрос о создании экземпляра определения класса

#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 подходит для любого типа.