Форум для программистов - задавайте интересные вопросы - получайте квалифицированные ответы
Непонятные проблемы с vtable
  • bootflasherbootflasher June 2011
    Здравствуйте уважаемые знатоки. Начинаю учить тонкости Qt (MinGW + Qt 4.5.1 + Eclipse + Qt Integration)
    Делаю следующее:
    ViewFactory.h

    class ViewFactory {
    public:
    virtual QObject * newInstance() const = 0;
    virtual QString getFactoryName() const = 0;
    virtual QString getFactoryDesc() const = 0;
    };

    Q_DECLARE_INTERFACE(ViewFactory,"com.tisadb.ViewFactory\0.1")


    Потом:
    tableview.h

    class tableviewFactory : public QObject, public ViewFactory
    {
    Q_OBJECT
    Q_INTERFACES(ViewFactory)
    public:
    QObject * newInstance() const { return const_cast((QObject *)new tableview()); };
    QString getFactoryName() const { return QString("TableView"); };
    QString getFactoryDesc() const { return QString("TableView version 0.1"); };
    };



    Если в таком виде компилирую проект то все работает нормально но если пытаюсь сделать более универсальный код:
    Factory.h

    #define FACTORY_INTERFACE(INTERFACE,INTERFACEDESC) \
    class INTERFACE##Factory { \
    public: \
    virtual QObject * newInstance() const = 0; \
    virtual QString getFactoryName() const = 0; \
    virtual QString getFactoryDesc() const = 0; \
    }; \
    Q_DECLARE_INTERFACE(INTERFACE##Factory,INTERFACEDESC)

    #define FACTORY(CLASS,INTERFACE,CLASSNAME,CLASSDESC) \
    class CLASS##Factory : public QObject, public INTERFACE##Factory { \
    Q_OBJECT \
    Q_INTERFACES(INTERFACE##Factory) \
    public: \
    QObject * newInstance() const { return const_cast((QObject *)new CLASS()); }; \
    QString getFactoryName() const { return QString(CLASSNAME); }; \
    QString getFactoryDesc() const { return QString(CLASSDESC); }; \
    };


    ViewFactory.h

    FACTORY_INTERFACE(View,"com.tisadb.ViewFactory\0.1")


    tableview.h

    FACTORY(tableview,View,"TableView","TableView verson 0.1")


    Если же в этом случае компилирую проэкт, то при линковке выводится ошибка:

    (.text$_ZN16tableviewFactoryC1Ev[tableviewFactory::tableviewFactory()]+0x2e): undefined reference to `vtable for tableviewFactory'
    D:/Devel/tisaprj/tableview/../../qt-win-opensource-src-4.5.1/include/QtCore/../../src/corelib/tools/qlist.h:(.text$_ZN16tableviewFactoryC1Ev[tableviewFactory::tableviewFactory()]+0x3a): undefined reference to `vtable for tableviewFactory'
  • beos92beos92 June 2011
    Это происходит скорее всего из-за того, что moc не распознает класс с Q_OBJECT, который делается с помощью #define FACTORY.
    moc парсит исходники до отработки препроцессора и такие подстановки делать не умеет.

    moc пробегается по исходникам и выбирает классы, в которых есть макрос Q_OBJECT, и для этих классов генерируется специальные файлы moc_*.cpp.
    Поэтому, для правильной генерации этих файлов необходимо, что бы moc находил в классе макрос Q_OBJECT, т.е.:

    class Obj : public QObject
    {
    Q_OBJECT
  • bootflasherbootflasher June 2011
    Короче решил проблему так:
    Factory.h
    #define FACTORY_INTERFACE \
    virtual QObject * newInstance() const = 0; \
    virtual QString getFactoryName() const = 0; \
    virtual QString getFactoryDesc() const = 0; \


    #define FACTORY(CLASS,CLASSNAME,CLASSDESC) \
    public: \
    QObject * newInstance() const { return const_cast((QObject *)new CLASS()); }; \
    QString getFactoryName() const { return QString(CLASSNAME); }; \
    QString getFactoryDesc() const { return QString(CLASSDESC); }; \
    private:

    ViewFactory.h
    class ViewFactory {
    public:
    FACTORY_INTERFACE
    };

    Q_DECLARE_INTERFACE(ViewFactory,"com.tisadb.ViewFactory\0.1")

    tableview.h
    class tableviewFactory : public QObject, public ViewFactory
    {
    Q_OBJECT
    Q_INTERFACES(ViewFactory)
    public:
    FACTORY(tableview,"TableView", "TableView version 0.1")
    };

    Конечно не то что хотелось бы, если у кого будут еще сообращения - делитесь
  • acidlynxacidlynx June 2011
    Конечно, накостылял ты тут (хотя идея хорошая). Убери объявления factory из дефайнов. Сделай класс-родитель для tablviewFactory и ViewFactory, в котором будут определяться твои функции newInstance, getFactoryName, getFactoryDesc. А потом уже наследуй от него и переопределяй те методы, которые нужно переопределить.

    И еще, неужели у тебя с таким кодом подсказки кода работают корректно?

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

Похоже, что Вы здесь впервые. Если хотите поучаствовать, нажмите на одну из этих кнопок!

Sign In with Twitter Sign In with OpenID Sign In with Google Login with Facebook

Войти Зарегистрироваться

In this Discussion

Tagged

Webparadox - разработка мобильных приложений под iOS и Android.