Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Alex_C от Май 27, 2012, 13:04



Название: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 27, 2012, 13:04
Делаю сингл-паттерн:

Код:
#ifndef FLAGOBJECT_H
#define FLAGOBJECT_H

#include <QByteArray>
#include <QMap>
#include <QString>
#include <QVector>

class QImage;
class QColor;

class FlagObject
{
public:
    static FlagObject *instance;
    static FlagObject* getInstance()
    {
        if(!instance)
            instance = new FlagObject();
        return instance;
    }
    ~FlagObject();
    void getFlag(int flagNum, QImage &image);

private:
    FlagObject();
    bool openDatFile(QString fileName);

    int m_FlagCount;
    QVector<QColor> *m_FlagBuffer;
    QMap<int, QString> *m_ColorMap;

    void init_ColorMap()
    {
        m_ColorMap = new QMap<int, QString>;
        m_ColorMap->insert(0, "black");
        m_ColorMap->insert(1, "darkRed");
        m_ColorMap->insert(2, "darkGreen");
        m_ColorMap->insert(3, "darkYellow");
        m_ColorMap->insert(4, "darkBlue");
        m_ColorMap->insert(5, "darkMagenta");
        m_ColorMap->insert(6, "darkCyal");
        m_ColorMap->insert(7, "darkGray");
        m_ColorMap->insert(8, "lightGray");
        m_ColorMap->insert(9, "red");
        m_ColorMap->insert(10, "green");
        m_ColorMap->insert(11, "yellow");
        m_ColorMap->insert(12, "blue");
        m_ColorMap->insert(13, "magenta");
        m_ColorMap->insert(14, "cyan");
        m_ColorMap->insert(15, "white");
    }
};

#endif // FLAGOBJECT_H

Компилю - без ошибок.

Пытаюсь его использовать -

Код:
#include "flagviewdelegate.h"
#include "flagobject.h"

FlagViewDelegate::FlagViewDelegate(QObject *parent) :
    QItemDelegate(parent)
{
}

void FlagViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                             const QModelIndex &index) const
{
    FlagObject *flagObject = FlagObject::getInstance();
}

Получаю ошибку:

./Obj\release\flagviewdelegate.o:flagviewdelegate.cpp:(.text+0x8): undefined reference to `FlagObject::instance'

Понимаю, что где-то что-то не так указал. Но у меня уже 2 аналогичных паттерна в программе есть - без проблем работают. А тут почему ошибка вылазиет?


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Serr500 от Май 27, 2012, 13:20
В cpp-файле надо написать:
Код:
FlagObject *FlagObject::instance = NULL;


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 27, 2012, 13:34
Это понятно, что нулем нужно инициировать. Ошибка то от этого не исчезнет.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: V1KT0P от Май 27, 2012, 13:48
Это понятно, что нулем нужно инициировать. Ошибка то от этого не исчезнет.
Исчезнет. Добавь как тебе сказали строку в cpp-файл. Или выложи минимальный проект.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 27, 2012, 14:39
Дело в том, что не могу я добавить эту строку. Появляется описанная ошибка при попытке обращения instance.

Вот прилагаю вообще пустой проект, где возникает эта ошибка.
У меня ошибка возникает здесь:

Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "testsingle.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    TestSingle *t = TestSingle::getInstance(); // Ошибка в этой строке.
}

MainWindow::~MainWindow()
{
    delete ui;
}


Название: Re: Непонятная ошибка undefined reference to
Отправлено: V1KT0P от Май 27, 2012, 14:46
Дело в том, что не могу я добавить эту строку. Появляется описанная ошибка при попытке обращения instance.
Ну так добавь, я вот добавил и все компилится.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 27, 2012, 14:56
Тьфу БЛИИИИИИИИИИИИИИИИИИИИН!
Все, на сегодня программировать хватит! Это ж надо так тупить!
Спасибо большое - Serr500 & V1KT0P - у меня ж у 2-х других паттернов аналогичных все работает, потому как эта строка присутствует.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Май 27, 2012, 17:50
А разве instance не должен быть приватным?

Код
C++ (Qt)
public:
   static FlagObject *instance;


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 28, 2012, 00:52
Нет конечно. Это один из самых простых и "правильных"паттернов))


Название: Re: Непонятная ошибка undefined reference to
Отправлено: alexis031182 от Май 28, 2012, 07:36
А где удаляется созданный инстанс FlagObject'а?


Название: Re: Непонятная ошибка undefined reference to
Отправлено: sidsukana от Май 28, 2012, 09:05
Перед описанием класса добавьте

Код:
class FlagObject;

Нужно предопределить класс, если хотите сразу же его использовать.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Май 28, 2012, 09:33
Нет конечно. Это один из самых простых и "правильных"паттернов))
Если оставить его публичным смысла в функции getInstance становится ровно 0.04 и такой класс перестает быть синглтоном.
А становится непонятно чем.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Май 28, 2012, 09:35
Перед описанием класса добавьте

Код:
class FlagObject;

Нужно предопределить класс, если хотите сразу же его использовать.
Это вроде лишнее. Он же используется внутри самого класса.
А внутри класса класс сам себе известен  ;D


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 28, 2012, 19:13
А где удаляется созданный инстанс FlagObject'а?

Удаляется так:

delete FlagObject::instance;

в "основном" классе)))



Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 28, 2012, 19:15
Если оставить его публичным смысла в функции getInstance

Удалять как тогда? Кстати идея то совсем не моя - в инете есть весьма хорошая статья по поводу использования сингл-паттерна.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: alexis031182 от Май 28, 2012, 19:18
Удаляется так:
delete FlagObject::instance;
в "основном" классе)))
Не удобно


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Kurles от Май 28, 2012, 22:21
Тоже может быть не удобно и противоречит паттерну "одиночка", но сейчас делаю так:
.h
Код
C++ (Qt)
class Example : public QObject
{
   Q_OBJECT
public:
   explicit Example(QObject *parent = 0);
   static Example* instanse();
   //...
 
private:
   static Example* _instanse;
   //...
};

.cpp
Код
C++ (Qt)
Example* Example::_instanse = 0;
 
Example::Example(QObject *parent) :
   QObject(parent)
{
   if (!_instanse)
       _instanse = this;
   //...
}
 
Example *Example::instanse()
{
   return _instanse;
}

в основном классе в конструкторе создаем единственный экземпляр класса:
Код
C++ (Qt)
   new Example(this);

и в любом месте программы для получения указателя на наш класс:
Код
C++ (Qt)
   Example* ex = Example::instanse();
При уничтожении основного класса корректно уничтожается и наш "одиночка".


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Май 28, 2012, 23:14
Вы наверное не до конца понимаете принцип патерна-одиночки - иначе зачем "единственный экземпляр класса"? Все нормально - не надо следовать моде - создавать никому не нужные, но "правильные" паттерны. Я думаю тут паттерн не нужен.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: alexis031182 от Май 28, 2012, 23:34
Вот пример синглтона (Майерса) из вики:
Код:
class OnlyOne
{
public:
   static OnlyOne &Instance() {
      static OnlyOne theSingleInstance;
      return theSingleInstance;
   }

private:       
   OnlyOne() {}
   OnlyOne(const OnlyOne&);
   OnlyOne &operator=(const OnlyOne&);
};
Что мне здесь нравится:
- единственный объект класса создаётся статически - нет нужды заботиться о его удалении;
- доступ к объекту класса можно получить лишь в одной точке, функции - Instance();
- конструктор, конструктор копирования и оператор присваивания объявлены как private, что исключает создание и манипуляции с копиями единственного объекта класса во вне;
- конструктор копирования и оператор присваивания не имеют определения - имеем error от компилятора при попытке использования изнутри;


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Май 29, 2012, 02:59
Если оставить его публичным смысла в функции getInstance

Удалять как тогда? Кстати идея то совсем не моя - в инете есть весьма хорошая статья по поводу использования сингл-паттерна.
Видимо ты ее не прочитал.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: sidsukana от Май 29, 2012, 06:07
Если это класс Q_OBJECT то можно объявить вместо тех 3 строчек макрос Q_DISABLE_COPY(MyClass).


Название: Re: Непонятная ошибка undefined reference to
Отправлено: alexis031182 от Май 29, 2012, 07:29
Если это класс Q_OBJECT то можно объявить вместо тех 3 строчек макрос Q_DISABLE_COPY(MyClass).
Вместо двух


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 14, 2012, 15:00
Видимо ты ее не прочитал.

Еще раз хочу поднять тему про паттерн-одиночка.

Действительно, не до конца разобрался. Однако хотелось бы прояснить некоторые нюансы.
Мне необходимо, чтоб если класс создавался, то он уже существовал до конца работы программы. По этому вариант предложенный alexis031182 мне не подходит. При использовании в ф-ции патерна, он будет уничтожаться при выходе из ф-ции.

Для меня получается правильный вариант, предложенный Kurles. Однако пока не понятен вопрос - как правильно удалить теперь паттерн с вызовом его деструктора при завершении работы программы?


Название: Re: Непонятная ошибка undefined reference to
Отправлено: mutineer от Июнь 14, 2012, 15:08
Мне необходимо, чтоб если класс создавался, то он уже существовал до конца работы программы. По этому вариант предложенный alexis031182 мне не подходит. При использовании в ф-ции патерна, он будет уничтожаться при выходе из ф-ции.

Это ж статический объект, не будет он уничтожаться при выходе из функции


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 14, 2012, 15:14
Это ж статический объект, не будет он уничтожаться при выходе из функции

Сейчас дебаггером проверил:
Если я в ф-ции определяю OnlyOne s = OnlyOne::Instance; (паттерн определен как у alexis031182)
при выходе из ф-ции вызывается деструктор OnlyOne. Это и верно - переменная s - получается локальная.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: alexis031182 от Июнь 14, 2012, 15:17
Сейчас дебаггером проверил:
Если я в ф-ции определяю OnlyOne s = OnlyOne::Instance; (паттерн определен как у alexis031182)
при выходе из ф-ции вызывается деструктор OnlyOne. Это и верно - переменная s - получается локальная.
:)
Код:
OnlyOne &s = OnlyOne::Instance;


Название: Re: Непонятная ошибка undefined reference to
Отправлено: mutineer от Июнь 14, 2012, 15:21
Это ж статический объект, не будет он уничтожаться при выходе из функции

Сейчас дебаггером проверил:
Если я в ф-ции определяю OnlyOne s = OnlyOne::Instance; (паттерн определен как у alexis031182)
при выходе из ф-ции вызывается деструктор OnlyOne. Это и верно - переменная s - получается локальная.


А вот у меня такая строка не компилируется и правильно делает - конструктор копирования приватный ведь, а тут происходит как раз создание нового объекта копированием. Ну или просто создание нового объекта (конструктор по умолчанию приватный) и выполнение оператора =(который тоже приватный). Так что фигня у тебя какая-то


Название: Re: Непонятная ошибка undefined reference to
Отправлено: iroln от Июнь 14, 2012, 15:40
Нет конечно. Это один из самых простых и "правильных"паттернов))


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex Custov от Июнь 14, 2012, 21:25
Для меня получается правильный вариант, предложенный Kurles. Однако пока не понятен вопрос - как правильно удалить теперь паттерн с вызовом его деструктора при завершении работы программы?

Если синглтон наследуется от QObject и является ребёнком какого-то основного объекта типа окна, то он сам удалится.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 15, 2012, 14:14
Если синглтон наследуется от QObject и является ребёнком какого-то основного объекта типа окна, то он сам удалится.

Да, думаю самый правильный метод.
В соседней ветке как раз дали ссылку на реализацию подобного сиглтона
http://blog.ufna.ru/2010/04/24/singleton-for-qt
однако в данной реализации мне вот что не понятно - при использовании синглтона типа

Код:
class MapObject
{
public:
    static MapObject *getInstance()
    {
        if(!instance)
            instance = new MapObject();
        return instance;
    }
    ~MapObject();

private:
    static MapObject *instance;
    MapObject();
}

Мы при помощи instance = new MapObject(); создаем новый объект вызывая его метод Create.
А если пользоваться тем примером, что приведен по ссылке

Код:
    static T& instance()
    {
        Q_ASSERT_X(s_pInstance, "instancing", "The singleton has not yet been created.");
        return (*s_pInstance);
    }

private:
    // Data...
    //----------------------------------------------------------------------
    static T* s_pInstance;

Нам нужно перед вызовом MyClass, наследника от синглтона, его явным образом создать, передав ему родителя.
Но какой же тогда получается это синглтон? Или я чего то не понимаю?


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 15, 2012, 15:04
В общем на основе
http://blog.ufna.ru/2010/04/24/singleton-for-qt
сделал свой шаблон синглтона. На мой взгляд более простой в использовании.

Код
C++ (Qt)
//--------------------------------------------------------------------------
// File: a_singleton.h
//
// Desc: An one-instance class
//--------------------------------------------------------------------------
 
#ifndef A_SINGLETON_H
#define A_SINGLETON_H
 
#include <QtGlobal>
 
// disable the warning regarding 'this' pointers being used in
// base member initializer list. Singletons rely on this action
// #pragma warning(disable : 4355)
 
//--------------------------------------------------------------------------
// Name: uSingleton
// Desc: A singleton is a type of class of which only one instance may
//    exist. This is commonly used for management classes used to
//    control system-wide resources.
//--------------------------------------------------------------------------
 
template <class T>
class uSingleton
{
public:
 
   // the singleton must be constructed with a reference to the controlled object
   //----------------------------------------------------------------------
   uSingleton(T& rObject)
   {
       Q_ASSERT_X(!s_pInstance, "constructor", "Only one instance of this class is permitted.");
       s_pInstance = &rObject;
   }
 
   // the singleton accessor
   //----------------------------------------------------------------------
   ~uSingleton()
   {
       Q_ASSERT_X(s_pInstance, "destructor", "The singleton instance is invalid.");
       s_pInstance = 0;
   }
 
   // the singleton accessor
   //----------------------------------------------------------------------
   static T& instance()
   {
       if(!s_pInstance)
           s_pInstance = new T();
       Q_ASSERT_X(s_pInstance, "instancing", "The singleton has not yet been created.");
       return (*s_pInstance);
   }
 
   // delete singleton
   static void deleteSingleton()
   {
       if(s_pInstance)
       {
           delete s_pInstance;
           s_pInstance = 0;
       }
   }
 
private:
   // Data...
   //----------------------------------------------------------------------
   static T* s_pInstance;
 
   // Nonexistant Functions...
   //----------------------------------------------------------------------
   uSingleton(const uSingleton& Src);
   uSingleton& operator=(const uSingleton& Src);
 
};
template <class T> T* uSingleton<T>::s_pInstance = 0;
 
#endif // A_SINGLETON_H
 

Теперь его действительно можно использовать просто

Код:
MY_CLASS.testFunc();

как и указано в ссылке.
Ф-ция static void deleteSingleton() нужна для удаления синглтона.

P.S. А какую кнопочку нажать, чтоб ком у меня в сообщениях выделялся цветами? :)


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex Custov от Июнь 15, 2012, 15:12
code=cpp


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 15, 2012, 15:19
code=cpp

Спасибо большое!


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Июнь 15, 2012, 16:19
code=cpp

Спасибо большое!
А сама кнопочка - это комбобокс под конопочками жирностью/курсивом, там можно выбрать язык расцветки.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 15, 2012, 20:54
А сама кнопочка - это комбобокс под конопочками жирностью/курсивом, там можно выбрать язык расцветки.

Вот тут пожалуйста по подробнее - я этот комбобокс конечно видел - меня и удивляло, что ничего не подсвечивается :)
Вот сейчас пишу - у меня там написано "C++ (Qt)" - а если нажимаешь на кнопку "Код" - все серым вставляется.
Вот когда ручками дописываешь code=cpp - все ок! Что я не так делаю?


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Июнь 15, 2012, 22:56
А сама кнопочка - это комбобокс под конопочками жирностью/курсивом, там можно выбрать язык расцветки.

Вот тут пожалуйста по подробнее - я этот комбобокс конечно видел - меня и удивляло, что ничего не подсвечивается :)
Вот сейчас пишу - у меня там написано "C++ (Qt)" - а если нажимаешь на кнопку "Код" - все серым вставляется.
Вот когда ручками дописываешь code=cpp - все ок! Что я не так делаю?
Я затрудняюсь ответить, что ты делаешь не так)
Выбери в этом списке любой элемент, кроме первого (он почему-то называется С++ Qt, хотя имеет значение "ничего не выбрано") и вставится нужный тег.
Действующий С++ Qt находится ниже.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 16, 2012, 14:53
Выбери в этом списке любой элемент, кроме первого (он почему-то называется С++ Qt, хотя имеет значение "ничего не выбрано") и вставится нужный тег.
Действующий С++ Qt находится ниже.

Спасибо! Действительно,  смущает, что первый элемент как бы С++ Qt . Вот по этому и не получалось. Еще раз спасибо!


Название: Re: Непонятная ошибка undefined reference to
Отправлено: twp от Июнь 18, 2012, 14:13
В общем на основе
http://blog.ufna.ru/2010/04/24/singleton-for-qt
сделал свой шаблон синглтона. На мой взгляд более простой в использовании.


Вместо
Код
C++ (Qt)
static T* s_pInstance;
 
лучше использовать QScopedPointer т.е.
Код
C++ (Qt)
static QScopedPointer<T> s_pInstance;
...
template <class T>
QScopedPointer<T> uSingleton<T>::s_pInstance;
 
Тогда deleteSingleton() в принципе не нужен, поскольку QScopedPointer будет автоматически удалять указатель при закрытии приложения.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Июнь 18, 2012, 18:49
В общем на основе
http://blog.ufna.ru/2010/04/24/singleton-for-qt
сделал свой шаблон синглтона. На мой взгляд более простой в использовании.


Вместо
Код
C++ (Qt)
static T* s_pInstance;
 
лучше использовать QScopedPointer т.е.
Код
C++ (Qt)
static QScopedPointer<T> s_pInstance;
...
template <class T>
QScopedPointer<T> uSingleton<T>::s_pInstance;
 
Тогда deleteSingleton() в принципе не нужен, поскольку QScopedPointer будет автоматически удалять указатель при закрытии приложения.
А почему нельзя просто static SingletonClass pInstance;
Зачем создавать динамически, а потом думать, как удалить?


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 19, 2012, 11:00
Тогда deleteSingleton() в принципе не нужен, поскольку QScopedPointer будет автоматически удалять указатель при закрытии приложения.

Да спасибо! Отличная идея!


Название: Re: Непонятная ошибка undefined reference to
Отправлено: Alex_C от Июнь 19, 2012, 11:03
А почему нельзя просто static SingletonClass pInstance;
Зачем создавать динамически, а потом думать, как удалить?

Может я чего не правильно сделал, но при этом у меня не происходило вызова конструктора.


Название: Re: Непонятная ошибка undefined reference to
Отправлено: andrew.k от Июнь 19, 2012, 12:02
А почему нельзя просто static SingletonClass pInstance;
Зачем создавать динамически, а потом думать, как удалить?

Может я чего не правильно сделал, но при этом у меня не происходило вызова конструктора.
Это невозможно.