Естественно, у меня есть тривиальный вопрос: мы нажимаем кнопку -> увеличивается счетчик, увеличивается счетчик -> значение QLabel обновляется. Я поймал странную ошибку и не хочу делать. Я не тупой в C ++, но я в QT. Это мое первое и самое тривиальное приложение.

Некоторые ответы там (о переполнении стека) советуют добавить виртуальный конструктор. Это не имеет никакого эффекта.

Я пытался переписать сигналы и слоты в новый стиль qt5, но были другие проблемы, мне было лень их исправлять, было ли это (переписывание, а не лень :)) хорошим способом, может быть проблема действительно в версиях?

Я просто не пытался переустановить QT или установить Qt4, может быть, проблема в этом?

о версиях .

$ qmake --version

Отвечает :

QMake version 3.0
Using Qt version 5.5.1 in /usr/lib/x86_64-linux-gnu

< Сильный > conn.pro :

TEMPLATE = app

QT += core gui

TARGET = conn
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

SOURCES += main.cpp

< Сильный > main.cpp :

#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QObject>

class Counter : public QObject {
    Q_OBJECT

private:
    double i_;

public:
    virtual ~Counter()
    {

    }
    Counter() : QObject(), i_(0)
    {
    }


public slots:
    void slot_incCounter();

signals:
    void goodbye(){}
    void counterChanged(double){}
};

void Counter::slot_incCounter() {
    emit counterChanged(++i_);
    if (i_ == 5) {
        emit goodbye();
    }
}

int main(int argc, char* argv[]) {
    QApplication my_app(argc, argv);

    QLabel label1("label i created");
    label1.show();

    QPushButton button1("press me");
    button1.show();

    Counter counter1;

    QObject::connect(&button1, SIGNAL(clicked()),
                     &counter1, SLOT(slot_incCounter()));

    QObject::connect(&counter1, SIGNAL(counterChanged(double a)),
                     &label1, SLOT(setNum(double a)));

    QObject::connect(&counter1, SIGNAL(goodbye()),
                     &my_app, SLOT(quit()));

    return my_app.exec();
}

Попробуйте запустить его:

qmake && make && ./conn 

Итак, я вижу в консоли:

g++ -m64 -Wl,-O1 -o conn main.o   -L/usr/X11R6/lib64 -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
main.o: In function `main':
main.cpp:(.text.startup+0xd6): undefined reference to `vtable for Counter'
collect2: error: ld returned 1 exit status
Makefile:144: recipe for target 'conn' failed
make`:` *** [conn] Error 1

Что мне делать?

0
Victor Akhlynin 28 Май 2017 в 00:13

2 ответа

Лучший ответ

Большое спасибо! Ваш ответ был полным, полезным и сделал все более очевидным. Решение было: < Сильный > 1 . Переместить класс Counter в Counter.h С этого момента сообщение о vtable исчезло. Появились сообщения о том, что goodbye () и Counter :: counterChanged (double) имеют множественное определение. Первое определение было моим в Counter.cpp (WRONG WAY). Второй был в moc_Counter.cpp, сгенерированном утилитой MOC. Так:

< Сильный > 2 . Удалите определения (мои пустые определения) сигнальных функций , потому что moc делает свое собственное в файле moc_Counter.cpp:

// SIGNAL 0
void Counter::goodbye()
{
    QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR);
}

// SIGNAL 1
void Counter::counterChanged(double _t1)
{
    void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    QMetaObject::activate(this, &staticMetaObject, 1, _a);
}

И они вызывают проблему множественного определения.

Подводя итог, рабочий код:

< Сильный > main.cpp :

#include <QApplication>
#include "Counter.h"



int main(int argc, char* argv[]) {
    QApplication my_app(argc, argv);

    QLabel label1("1");
    label1.show();

    QPushButton button1("press me");
    button1.show();

    Counter counter1;

    QObject::connect(&button1, SIGNAL(clicked()),
                     &counter1, SLOT(slot_incCounter()));

    QObject::connect(&counter1, SIGNAL(counterChanged(double)),
                     &label1, SLOT(setNum(double)));

    QObject::connect(&counter1, SIGNAL(goodbye()),
                     &my_app, SLOT(quit()));

    return my_app.exec();
}


void Counter::slot_incCounter() {
    emit counterChanged(++i_);
    if (i_ == 5) {
        emit goodbye();
    }
}

< Сильный > Counter.h :

#ifndef COUNTER_H
#define COUNTER_H

#include <QLabel>
#include <QPushButton>
#include <QObject>

class Counter : public QObject {
    Q_OBJECT
private:
    double i_;

public:
    virtual ~Counter()
    {
    }

    Counter() : QObject()
    {
    }


public slots:
    void slot_incCounter();

signals:
    void goodbye();
    void counterChanged(double);
};

#endif // COUNTER_H

< Сильный > Counter.cpp :

#include "Counter.h"

Спасибо, ты молодец!

0
Victor Akhlynin 28 Май 2017 в 07:47

Qt использует компилятор мета-объектов (moc), чтобы включить, например, сигнал и слоты. По умолчанию он отлично работает, если макрос Q_OBJECT находится в заголовочном файле. Поэтому проще всего было бы поместить Counter в его собственный файл заголовка / реализации, повторно запустить qmake и make. (Это кстати хорошая практика ...)

Если вы хотите использовать один файл main.cpp, вам нужно явно указать moc, что этот файл содержит макросы, которые нужно проанализировать moc. Вы делаете это со следующей строкой в самом конце main.cpp:

#include "main.moc"

Затем также повторно запустите qmake и make.

Помните, что указание moc-include вручную - не лучший выбор. Так что лучше разбивайте свои классы C ++ на отдельные файлы с самого начала ...

1
Lorenz 27 Май 2017 в 21:42