【问题标题】:Why won't this compile (link) with the Q_OBJECT macro in place?为什么不使用 Q_OBJECT 宏编译(链接)?
【发布时间】:2010-08-31 08:22:55
【问题描述】:

我用 PyQt 制作了一个项目的原型并让它在那里工作,现在我正在尝试将它转换为 C++,但遇到了一些问题。

如果我不放入 Q_OBJECT 宏,它会编译并工作,但如果我将其注释掉,我会收到以下错误:

Undefined symbols:
  "vtable for MapView", referenced from:
      MapView::~MapView()in mapview.o
      MapView::~MapView()in mapview.o
      MapView::MapView(QObject*)in mapview.o
      MapView::MapView()in mapview.o
  "MapView::staticMetaObject", referenced from:
      MapView::MapView(QObject*)in mapview.o
      MapView::MapView()in mapview.o

这是标题:

#ifndef MAPVIEW_H
#define MAPVIEW_H

#include <QtGui>
#include <QObject>

class MapView : public QGraphicsScene
{
    //Q_OBJECT

public:
    MapView();
    explicit MapView(QObject *parent = 0);
    QGraphicsPixmapItem *mappixmap;
    ~MapView();

private:
    bool dragging;
    float offsetX, offsetY, downoffsetX, downoffsetY;

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

};

#endif // MAPVIEW_H

第二个问题是如果我在这里省略 Q_OBJECT 宏会发生坏事吗?

是的,我知道将 QGraphicsScene 称为“视图”是愚蠢的。

【问题讨论】:

  • 我将根据请求发布功能实现,我只是不想一次将所有内容都发布在这里......

标签: c++ qt linker qobject


【解决方案1】:

这种错误通常发生在您添加Q_OBJECT 宏而忘记重新运行moc 时。如果您使用qmake,只需在添加宏后运行make qmake

至于您的第二个问题:如果没有 Q_OBJECT 宏,您将无法使用信号/插槽(除其他外)。有关更多信息,请参阅docs

【讨论】:

  • 谢谢,重新运行 qmake 确实可以解决这个问题!我真的不需要在这里使用信号和插槽,只需接收对我定义的事件处理程序的调用。但我还是想以正确的方式做事。
  • @teukkam,如果你的类继承自QObject,你将需要Q_OBJECT宏...
  • @liaK:不,您只需要它用于信号/插槽和其他一些东西。请参阅我的答案中的链接。
  • 显然我不需要那个宏,因为即使我省略了它,程序也会按预期工作。我只是想把它放在那里,这样代码看起来就像人们期望它在典型情况下的样子。
  • @ Job, doc.trolltech.com/4.6/metaobjects.html 查看此链接。从文档中,我们强烈建议 QObject 的所有子类都使用 Q_OBJECT 宏,无论它们是否实际使用信号、槽, 和属性。
【解决方案2】:

最近我尝试在 Linux 上编译 QDeviceWatcher 并得到相同的错误 WRT QDeviceWatcherPrivate 类,该声明可以在 qdevicewatcher_p.hqdevicewatcher_linux.cpp 中找到定义(在 Linux)。

我使用 cmake 作为构建系统,我的 CMakeLists.txt 看起来像:

cmake_minimum_required(VERSION 3.8)

project("QDeviceWatcher" LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOMOC ON)

find_package(Qt5 REQUIRED COMPONENTS Core Network)

set(SOURCES)
list(APPEND SOURCES "qdevicewatcher.cpp")
if(WINCE)
    list(APPEND SOURCES "qdevicewatcher_wince.cpp")
elseif(WIN32)
    list(APPEND SOURCES "qdevicewatcher_win32.cpp")
elseif(APPLE)
    list(APPEND SOURCES "qdevicewatcher_mac.cpp")
elseif(UNIX)
    list(APPEND SOURCES "qdevicewatcher_linux.cpp")
else()
    message(FATAL_ERROR "no supported platform detected")
endif()

add_library(${PROJECT_NAME} STATIC ${SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC ".")

target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Network)

set_target_properties(${PROJECT_NAME} PROPERTIES
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS YES
    )

正如您在add_library 中看到的,我只提供*.cpp 文件。我怀疑,cmake 运行 Meta 对象编译器 并查看所有源,可能除了 #include 依赖项之外,哪些文件名(无扩展名)与 *.cpp 不匹配的文件名(只是假设),用于 QObject/QWidget/... 基础和 Q_OBJECT 宏。我认为 cmake 错过了 qdevicewatcher_p.h 来查看并针对它运行 MOC

在我将“qdevicewatcher_p.h”添加到源列表后,错误不再存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    相关资源
    最近更新 更多