QT C++前向声明问题?

4

我正在尝试使用QTPropertyBrowser来编辑我的QObjects的属性。 从QT Solutions的“QtPropertyBrowser”示例中,我在我的项目中使用以下文件。

http://qt.gitorious.org/qt-solutions/qt-solutions/blobs/master/qtpropertybrowser/examples/object_controller/objectcontroller.cpp

http://qt.gitorious.org/qt-solutions/qt-solutions/blobs/master/qtpropertybrowser/examples/object_controller/objectcontroller.h

我将我的CMakeFile配置如下:

#include_directories("/usr/include")
SET(QTVIEW_SRCS 
  src/main.cpp  
  src/TestWidget.cpp
  src/plugin/IPlugin.cpp
  src/objectcontroller.cpp
)

SET(QTVIEW_MOH_HDRS
 src/TestWidget.h
 src/plugin/IPlugin.h
 src/objectcontroller.h

)

当我按照现有文件进行编译时,编译器会出现以下错误 -
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx: 在成员函数 'virtual int ObjectController::qt_metacall(QMetaObject::Call, int, void**)' 中: C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73: 错误:无效使用不完整类型 'struct ObjectControllerPrivate' C:\svn\osaka3d\trunk\osaka3d\QTView\src/objectcontroller.h:45: 错误:前向声明 'struct ObjectControllerPrivate' C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73: 错误:'QtProperty' 前面需要类型说明符 C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73: 错误:'QtProperty' 前面需要 '>' C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73: 错误:'QtProperty' 前面需要 '(' C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73: 错误:该作用域中未声明 'QtProperty' C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73: 错误:')' 之前需要主表达式 mingw32-make2: * [CMakeFiles/qtview.dir/src/moc_objectcontroller.cxx.obj] 错误 1 mingw32-make1: [CMakeFiles/qtview.dir/all] 错误 2 mingw32-make: ** [all] 错误 2

但是当我注释掉这行代码:

Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QVariant &))

在"objectcontroller.h"中

并注释掉以下行:

#include "moc_objectcontroller.cxx"

在文件"objectcontroller.cpp"的末尾,编译通过了,但我无法使用SIGNALS/SLOTS来反映QObject参数的编辑。有什么提示吗?
2个回答

6

我遇到了同样的问题(我是Qt新手,但这对我有用)。对于其他寻找解决方案的人,我发现了以下内容:

发生了什么

问题在于由于Q_PRIVATE_SLOT宏,生成的moc_XXX.cxx需要完整声明XXXPrivate类来调用私有槽函数。由于公共头文件只是前向声明它,生成的cxx无法单独编译。 QtPropertyBrowser团队通过在其源文件中包含生成的moc_XXX.cpp(注意'pp',cmake生成'xx')来规避此问题(丑陋,但有效)。我也不知道告诉moc包括(在这种情况下甚至不存在的)私有XXX_p.hpp的任何其他方法。所以让我们坚持这种方式。

接下来我做的是从可执行文件中删除生成的moc_XXX.cxx文件,但这导致moc从未被调用。即使我使用了QT4_WRAP_CPP。所以经过进一步搜索,我发现...

对于这种特殊情况的一个补充:缺少QtProperty声明。请添加以下前向声明或适当的包含文件:

#if QT_VERSION >= 0x040400
QT_BEGIN_NAMESPACE
#endif

class QtProperty;

#if QT_VERSION >= 0x040400
QT_END_NAMESPACE
#endif

解决方案

全文感谢 fullmetalcoder 提出了此 CMake 函数:

function(qt4_wrap_hdrs _moc_srcs)
  qt4_get_moc_flags(_moc_incs)
  set(_mocs)
  foreach(_current_file ${ARGN})
    get_filename_component(_abs_file ${_current_file} ABSOLUTE)
    if(EXISTS ${_abs_file})
      file(READ ${_abs_file} _contents)
      get_filename_component(_basename ${_abs_file} NAME_WE)
      string(REGEX MATCH "Q_OBJECT" _match "${_contents}")
      if(_match)
        set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp")
        qt4_create_moc_command(${_abs_file} ${_moc} "${_moc_incs}" "")
        macro_add_file_dependencies(${_abs_file} ${_moc})
        list(APPEND _mocs ${_moc})
      endif(_match)
    endif(EXISTS ${_abs_file})
  endforeach (_current_file)
  set(${_moc_srcs} ${_mocs} PARENT_SCOPE)
endfunction(qt4_wrap_hdrs)

你可以使用这个函数作为QT4_WRAP_CPP的替代品。现在你只需要在你的CMakeLists.txt中添加以下代码,以便编译器找到生成的moc_XXX.cpp文件(新函数创建了一个'pp'文件...)。 (来自http://www.qtcentre.org/threads/37428-using-QT-unit-testing-with-CMake
include_directories(${CMAKE_BINARY_DIR})

这个函数一直调用moc,并且更像是在qmake情况下的行为。当然,你可以轻松地进行源码构建。

但有一个注意点:所有的moc_XXX.cpp文件都会在CMAKE_BINARY_DIR中生成。所以如果你有两个文件include1/foo.hppinclude2/foo.hpp,其中一个将被覆盖!


1

此链接已失效。 - macetw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接