абстрактный тип класса, но все определено - PullRequest
0 голосов
/ 02 декабря 2018

В настоящее время я пишу версию задачи коммивояжера для университета, использующей qt.Чтобы разместить города в виджете QGraphicsView, я создал эту программу, как в этом уроке YouTube: https://www.youtube.com/watch?v=hgDd2QspuDg

К сожалению, я просто делаю все как в учебнике, но только я получаю сообщение об ошибке, что мой класс - абстрактный, чего я не понимаю, потому что все, что я помещаю в этот класс, я определяю в Кодексе, и в моем классе нет ничего, на что нет ссылок.

Dialog.h:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtCore>
#include <QtGui>
#include <QMessageBox>
#include <iostream>
#include <QPointF>
#include "mycity.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();
private slots:
    double on_Kelvin_box_valueChanged();

    double on_Iter_box_valueChanged();

    double on_Radius_box_valueChanged();

    double on_CVRatio_box_valueChanged();

    void on_resetButton_clicked();

    void on_startButton_released();

    void on_stopButton_released();

private:
    Ui::Dialog *ui;
    QGraphicsScene *scene;
    MyCity *city;

protected:

};

#endif // DIALOG_H

mycity.h:

#ifndef MYCITY_H
#define MYCITY_H

#include <QPainter>
#include <QGraphicsItem>
#include <QDebug>
#include <string.h>

class MyCity : public QGraphicsItem
{
public:
    MyCity();

    QRectF boundingRect() const;
    void paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget);
    bool Pressed;
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};

#endif // MYCITY_H

Dialog.cpp:

#include "dialog.h"
#include "ui_dialog.h"
#include <qtCore>
#include <qtGui>
#include <QPointF>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);

    city = new MyCity();
    scene->addItem(city);
}

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

double Dialog::on_Kelvin_box_valueChanged()
{
    double kelvin = ui->Kelvin_box->value();
    return kelvin;
}

double Dialog::on_Iter_box_valueChanged()
{
    double iter = ui->Iter_box->value();
    return iter;
}

double Dialog::on_CVRatio_box_valueChanged()
{
    double cvRatio = ui->CVRatio_box->value();
    return cvRatio;
}

double Dialog::on_Radius_box_valueChanged()
{
    double radius = ui->Radius_box->value();
    return radius;
}

void Dialog::on_resetButton_clicked()
{
   ui->Kelvin_box->setValue(0.3);
   ui->Iter_box->setValue(10000);
   ui->CVRatio_box->setValue(2.5);
   ui->Radius_box->setValue(0.1);
}

//Wenn dieser Knopf gedrückt wird startet die Iteration
void Dialog::on_startButton_released()
{

}
//Wenn dieser Knopf gedrückt wird beendet sich die Iteration
void Dialog::on_stopButton_released()
{

}

main.cpp:

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

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}

mycity.cpp:

#include "mycity.h"
//Das is das Objekt 'Stadt' welches wir erzeugen in der dialog.cpp
MyCity::MyCity()
{
    Pressed = false;
    setFlag(ItemIsMovable);
}

QRectF MyCity::boundingRect() const
{
   return QRectF(0,0,20,20);
}

void MyCity::paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //ellipse wird rot bei draufdrücken, grün bei loslassen
    QRectF rec = boundingRect();
    QBrush brush(Qt::green);
    if(Pressed)
    {
        brush.setColor((Qt::red));
    }
    else
    {
        brush.setColor((Qt::green));
    }

    painter->fillRect(rec,brush);
    painter->drawRect(rec);
}

void MyCity::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    //hier geschieht, was beim mausdruck passieren soll (stadt kreieren)
    Pressed = true;
    update();
    QGraphicsItem::mousePressEvent(event);//überschreiben der eigentlichen mousePressEvent-funktion
}

void MyCity::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    //nur temporäre testfunktion, wird am ende nich gebraucht
    Pressed = false;
    update();
    QGraphicsItem::mouseReleaseEvent(event);
}

И этоэто ошибка, которую я получаю:

C: ... \ dialog.cpp: 16: Ошибка: недопустимое новое выражение абстрактного типа класса 'MyCity' city = new MyCity ();

Может кто-нибудь помочь мне найти ошибку, которая вызывает этот абстрактный класс?

РЕДАКТИРОВАТЬ: Вот все сообщение об ошибке, которое я получил от qt:

..\Milestone_Traveling\dialog.cpp: In constructor 'Dialog::Dialog(QWidget*)':
..\Milestone_Traveling\dialog.cpp:16:31: error: invalid new-expression of abstract class type 'MyCity'
     MyCity* city = new MyCity();
                               ^
In file included from ..\Milestone_Traveling\dialog.h:10:0,
                 from ..\Milestone_Traveling\dialog.cpp:1:
..\Milestone_Traveling\mycity.h:9:7: note:   because the following virtual functions are pure within 'MyCity':
 class MyCity : public QGraphicsItem
       ^
In file included from D:\QT\5.10.1\mingw53_32\include\QtWidgets/QGraphicsItem:1:0,
                 from ..\Milestone_Traveling\mycity.h:5,
                 from ..\Milestone_Traveling\dialog.h:10,
                 from ..\Milestone_Traveling\dialog.cpp:1:
D:\QT\5.10.1\mingw53_32\include\QtWidgets/qgraphicsitem.h:344:18: note:     virtual void QGraphicsItem::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
     virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) = 0;
                  ^
Makefile.Debug:1144: recipe for target 'debug/dialog.o' failed
mingw32-make[1]: Leaving directory 'C:/…/build-Milestone_Traveling-Desktop_Qt_5_10_1_MinGW_32bit-Debug'
mingw32-make[1]: *** [debug/dialog.o] Error 1
Makefile:36: recipe for target 'debug' failed
mingw32-make: *** [debug] Error 2
15:48:32: Der Prozess "D:\QT\Tools\mingw530_32\bin\mingw32-make.exe" wurde mit dem Rückgabewert 2 beendet.
Fehler beim Erstellen/Deployment des Projekts Milestone_Traveling (Kit: Desktop Qt 5.10.1 MinGW 32bit)
Bei der Ausführung von Schritt "Make"
15:48:32: Verstrichene Zeit: 00:11.

1 Ответ

0 голосов
/ 02 декабря 2018

Всегда используйте ключевое слово override при переопределении виртуального метода.Если бы вы сделали это при написании MyCity::paint, вы бы поняли, что он не соответствует подписи для QGraphicsItem::paint:

QGraphicsItem:

virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) = 0;

MyCity:

void paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget);

Видите разницу?Это тонко, но вам не хватает const

Если бы вместо этого вы написали MyCity::paint с ключевым словом override, например, так:

void paint(QPainter *painter, QStyleOptionGraphicsItem *option, QWidget *widget) override;

Тогда вы получитеошибка компилятора в соответствии с

ошибкой: «virtual void MyCity :: paint (...)» помечена как «переопределить», но не переопределяет

...