错误:使用PIMPL时转发'class SActionPrivate'的声明

时间:2014-12-23 19:42:40

标签: c++ qt cmake pimpl-idiom moc

在Qt-program中我实现了Pimpl方法,有3个文件

saction.cpp

saction.h

saction_p.h - with a private class sactionPrivate

代码基于kdelibs的代码。我正在使用CMAKE作为构建系统。所以我在编译时遇到错误

build / moc_saction.cpp:73:22:错误:无效使用不完整类型'class SActionPrivate' actions / saction.h:492:18:错误:'class SActionPrivate'的前向声明

问题出在文件 moc_saction.cpp 中,它不包含文件 saction_p.h ,只有 saction.h < / p>

所以我需要在生成的moc文件中手动添加该行:

#include "../actions/saction_p.h"

我该怎么办,为了不手动纠正moc文件???

CMakeLists.txt

project(scalc)
cmake_minimum_required(VERSION 2.6)
find_package(Qt4 REQUIRED)

include_directories(
${QT_INCLUDES} 
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/actions
)

set(scalc_SRCS 

actions/saction.cpp

main.cpp )

set(CMAKE_AUTOMOC ON)

add_executable(scalc ${scalc_SRCS} )

target_link_libraries(scalc ${QT_QTCORE_LIBRARY}  ${QT_QTGUI_LIBRARY})
install(TARGETS scalc RUNTIME DESTINATION bin)

操作/ saction.h

#ifndef SACTION_H
#define SACTION_H

#include <QtGui/QWidgetAction>

class SAction : public QWidgetAction
{
    Q_OBJECT
    public:
        explicit SAction(QObject *parent);
        virtual ~SAction();

    private:
        friend class SActionPrivate;
        class SActionPrivate* const d;
        Q_PRIVATE_SLOT(d, void slotTriggered())
};


#endif

操作/ saction_p.h

#ifndef SACTION_P_H
#define SACTION_P_H

class SAction;


class SActionPrivate
{
    public:

        SActionPrivate():q(0)
        {
        }

        void slotTriggered();

        void init(SAction *q_ptr);

        SAction *q;

};

#endif

操作/ saction.cpp

#include "saction.h"
#include "saction_p.h"

#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
#include <QtGui/QShortcutEvent>
#include <QtGui/QToolBar>

void SActionPrivate::init(SAction *q_ptr)
{
  q = q_ptr;

  QObject::connect(q, SIGNAL(triggered(bool)), q,     SLOT(slotTriggered()));

    q->setProperty("isShortcutConfigurable", true);
}


void SActionPrivate::slotTriggered()
{}

SAction::SAction(QObject *parent)
    : QWidgetAction(parent), d(new SActionPrivate)
{
    d->init(this);
}

SAction::~SAction()
{
    delete d;
}

的main.cpp

#include "saction.h"

int main(int argc, char** argv)
{
    SAction gg(new QWidget());
}

由cmake moc_saction.cpp生成

#include "../actions/saction.h"
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'kaction.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 63
#error "This file was generated using the moc from 4.8.6. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
static const uint qt_meta_data_SAction[] = {

// content:
  6,       // revision
  0,       // classname
  0,    0, // classinfo
  1,   14, // methods
  0,    0, // properties
  0,    0, // enums/sets
  0,    0, // constructors
  0,       // flags
  0,       // signalCount

// slots: signature, parameters, type, tag, flags
  9,    8,    8,    8, 0x08,

  0        // eod
};

static const char qt_meta_stringdata_SAction[] = {
"SAction\0\0slotTriggered()\0"
};

void SAction::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
    Q_ASSERT(staticMetaObject.cast(_o));
    SAction *_t = static_cast<SAction *>(_o);
    switch (_id) {
    case 0: _t->d->slotTriggered(); break;
    default: ;
    }
}
Q_UNUSED(_a);
}

const QMetaObjectExtraData SAction::staticMetaObjectExtraData = {
0,  qt_static_metacall 
};

const QMetaObject SAction::staticMetaObject = {
{ &QWidgetAction::staticMetaObject, qt_meta_stringdata_SAction,
  qt_meta_data_SAction, &staticMetaObjectExtraData }
};

#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &SAction::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION

const QMetaObject *SAction::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}

void *SAction::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_SAction))
    return static_cast<void*>(const_cast< SAction*>(this));
return QWidgetAction::qt_metacast(_clname);
}

int SAction::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QWidgetAction::qt_metacall(_c, _id, _a);
if (_id < 0)
    return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
    if (_id < 1)
    qt_static_metacall(this, _c, _id, _a);
    _id -= 1;
}
return _id;
}
QT_END_MOC_NAMESPACE

1 个答案:

答案 0 :(得分:2)

是的,你在这里有两个问题:

  • 缺少生成moc的cmake二进制目录的includepath

    ${CMAKE_CURRENT_BINARY_DIR}
    
  • 您需要在相应的源文件末尾包含moc文件

    #include "moc_saction.cpp"