Qt继承和实例化问题

Joe*_*ing 2 c++ inheritance qt

我最近收到了一份我正在处理的应用程序.

在我已经偶然发现继承问题后不久.

我有一个名为ModelBase的基类,它有一个纯虚方法,使它成为一个抽象类.该课程如下:

#ifndef MODELBASE_H
#define MODELBASE_H

#include <QMetaType>
#include <QString>

class ModelBase
{
public:
    ModelBase();
    virtual ~ModelBase();

    long getId() const;
    void setId(const long id);

    virtual QString toString() const = 0;
private:
    long m_id;

};

Q_DECLARE_METATYPE(ModelBase)

#endif // MODELBASE_H
Run Code Online (Sandbox Code Playgroud)

事实上它被声明为METATYPE可能需要记住读取其余代码.

我从这个基类派生了几个类.对于这个例子,我将使用两个给我带来最多问题的例子.

#ifndef PLATFORM_H
#define PLATFORM_H

#include <QDate>

#include "modelbase.h"
#include "game.h"

class Platform : ModelBase
{
public:
    Platform();
    ~Platform();

    QString toString() const;

    QString getName();
    QDate getPublishDate();

    void setName(QString name);
    void setPublishDate(QDate publishDate);
private:
    QString m_name;
    QDate m_publishDate;
    QList<Game*> m_games;
};

#endif // PLATFORM_H
Run Code Online (Sandbox Code Playgroud)

如您所见,标头还包含父类ModelBase中的虚方法.

最后但并非最不重要的; 问题类:

#ifndef GAME_H
#define GAME_H

#include <QDate>

#include "modelbase.h"

class Platform;
class Publisher;
class Genre;

class Game : ModelBase
{
public:
    Game();
    ~Game();

    QString getTitle();
    Publisher* getPublisher();
    Genre* getGenre();
    Platform* getPlatform();
    QDate getPublishDate();
    QString getLentTo();

    void setTitle(QString title);
    void setPublisher(Publisher &publisher);
    void setGenre(Genre &genre);
    void setPlatform(Platform &platform);
    void setPublishDate(QDate date);
    void setLentTo(QString lentTo);

    QString toString() const;
private:
    QString m_title;
    Publisher *m_publisher;
    Genre *m_genre;
    Platform *m_platform;
    QDate m_publishDate;
    QString m_lentTo;
};

#endif // GAME_H
Run Code Online (Sandbox Code Playgroud)

既然代码到位了......

第一个问题来自循环依赖.

平台有很多游戏,游戏有一个平台.

我通过在games.h中声明平台并在platforms.h中包含games.h来解决这个问题

现在已经不在了,我编写了我的程序,得到了以下抱怨我真的不明白.

xxxxx\mingw47_32\include\QtCore\qmetatype.h:382: error: cannot allocate an object of abstract type 'ModelBase'
Run Code Online (Sandbox Code Playgroud)

确实公平.但我从来没有真正直接在类中定义ModelBase.只是源于它.

我在同一个日志中遇到的另一个错误是:

xxxx\mingw47_32\include\QtCore\qmetatype.h:-1: In instantiation of 'static void* QtMetaTypePrivate::QMetaTypeFunctionHelper<T, Accepted>::Create(const void*) [with T = ModelBase; bool Accepted = true]':
Run Code Online (Sandbox Code Playgroud)

我真的不知道这里发生了什么.

我尝试在games.h中根本不使用指针,但后来我得到了不同类型的编译器错误,我也不明白;

xxxx\game.h:38: error: field 'm_platform' has incomplete type
Run Code Online (Sandbox Code Playgroud)

我尝试过使用#include和forward声明,但它们都给了他们一些问题.还要注意,如果在games.h文件中,我用包括替换正向类声明(除了platform.h,这会带回循环依赖问题)所有问题都有不完整类型消失(除了m_platform,因为据我所知) ,我别无选择,只能向前宣布它)

我假设我不知道这个继承应该如何在这里工作.

我将ModelBase定义为元类型的原因是因为我想让ModelBase及其子元素从QVariant中包装/解包

Pix*_*ist 8

发生最后一个错误,因为您的类中没有不完整类型的对象.编译器不知道要为此对象分配多少空间,因此类的内存​​布局将以某种方式未定义.相反,"指向不完整"的指针是可能的.

我不是Qt,但看起来你的Q_DECLARE_METATYPE()导致构造函数调用.根据定义,抽象类不可构造.

QMetaTypeFunctionHelper::Create :

static void *Create(const void *t)
{
  if (t)
    return new T(*static_cast<const T*>(t));
  return new T();
}
Run Code Online (Sandbox Code Playgroud)

文档QMetaType类参考说:

Q_DECLARE_METATYPE(Type)只要它提供公共默认构造函数,公共复制构造函数和公共析构函数,该宏就会使QMetaType知道类型Type.需要在QVariant中使用Type类型作为自定义类型.

正如我所提到的:无法构造抽象类.

参见[Qt-interest] Q_DECLARE_METATYPE和抽象类:

星期一,8 de de de de 2011:12:36:16 Schimkowitsch Robert写道:

如何声明抽象基类的元类型?我在Q_DECLARE_METATYPE文档中没有看到任何禁止它的内容.

你没有.元类型需要是可默认构造的,可公开破坏的,可复制的和可分配的.

根本无法构造抽象类型.根据抽象的定义,您不希望复制它们,因为这样做会削减您拥有的专用对象.

您很可能希望将指针 的元类型注册到抽象类.


Jan*_*rát 5

Q_DECLARE_METATYPE抽象类确实是个问题.这不会"定义一个元类型的类",它使该类可用于Qt的MOC,例如在信号/槽参数中传递它,使其可用QVariant等等.但是,你不能在一个抽象的类上这样做 - 这没有道理.你确定你不是故意的:

Q_DECLARE_METATYPE(ModelBase*)
Run Code Online (Sandbox Code Playgroud)

关于其余警告 - 当编译器注意到错误时,大多数警告会尝试在源代码中查找其他问题.有时它运作良好,有时它只是给你虚假的警告.修复Q_DECLARE_METATYPE错误然后继续处理.