error C2039: “staticMetaObject”: 不是“A”的成员 c:\Users\chuan\documents\visual studio 2010\Projects\Deriv

转载自:https://blog.csdn.net/weixin_39955229/article/details/81901603

原文标题:QObject多继承static_meta_object的编译问题

问题描述

继承一个类,再继承自QObject并添加Q_OBJECT的宏之后,编译不过。

class A{public:

    A(){};

    ~A(){};

private:
    int m_aval;

};

class DerivedObject : public A,public QObject
{
    Q_OBJECT

public:
    DerivedObject();

    ~DerivedObject();

private:
    int m_dval;

};

错误信息

错误 1 error C2039: “staticMetaObject”: 不是“A”的成员 c:\Users\chuan\documents\visual studio 2010\Projects\DerivedObject\DerivedObject\GeneratedFiles\Debug\moc_derivedobject.cpp 53 DerivedObject

错误 2 error C2039: “qt_metacast”: 不是“A”的成员 c:\Users\chuan\documents\visual studio 2010\Projects\DerivedObject\DerivedObject\GeneratedFiles\Debug\moc_derivedobject.cpp 73 DerivedObject

错误 3 error C2039: “qt_metacall”: 不是“A”的成员 c:\Users\chuan\documents\visual studio 2010\Projects\DerivedObject\DerivedObject\GeneratedFiles\Debug\moc_derivedobject.cpp 78 DerivedObject

问题分析

首先,我们尝试输出该类的内存布局,分析错误原因。

vs下右键属性->配置属性->C/C++->命令行,在下方其他选项中填入:

/d1 reportSingleClassLayout**DerivedObject**

加粗部分是具体的类名,表示输出哪个类的内存布局情况,可以自定义,我这里用的类名是 DerivedObject

设置完保存,直接编译,

    +---
    | +--- (base class QObject)
 0  | | {vfptr}
 4  | | ?$QScopedPointer@VQObjectData@@U?$QScopedPointerDeleter@VQObjectData@@@@ d_ptr
    | +---
    | +--- (base class A)
 8  | | m_aval
    | +---
12  | m_dval
    +---

DerivedObject::$vftable@:
    | &DerivedObject_meta
    |  0
 0  | &DerivedObject::metaObject
 1  | &DerivedObject::qt_metacast
 2  | &DerivedObject::qt_metacall
 3  | &DerivedObject::{dtor}
 4  | &QObject::event
 5  | &QObject::eventFilter
 6  | &QObject::timerEvent
 7  | &QObject::childEvent
 8  | &QObject::customEvent
 9  | &QObject::connectNotify
10  | &QObject::disconnectNotify

DerivedObject::metaObject this adjustor: 0
DerivedObject::qt_metacast this adjustor: 0
DerivedObject::qt_metacall this adjustor: 0
DerivedObject::{dtor} this adjustor: 0
DerivedObject::__delDtor this adjustor: 0
DerivedObject::__vecDelDtor this adjustor: 0

注意这里虚函数表的展开,有几个虚函数地址。但是我们并没有在DerivedObject中重写任何虚函数,那么这个虚函数表的布局为什么是这样的呢?

注意类定义的开始,加入了一个宏Q_OBJECT,进入定义发现:

#define Q_OBJECT \
public: \
    Q_OBJECT_CHECK \
    static const QMetaObject staticMetaObject; \
    Q_OBJECT_GETSTATICMETAOBJECT \
    virtual const QMetaObject *metaObject() const; \
    virtual void *qt_metacast(const char *); \
    QT_TR_FUNCTIONS \
    virtual int qt_metacall(QMetaObject::Call, int, void **); \
private: \
    Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \
    Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);

也就是说,只要包含了Q_OBJECT着个宏,它就会在编译的时候展开为一堆定义和重写的虚函数,然后在MOC的时候在CPP中加入定义。比如此时对应的moc_derivedobject.cpp里编译器自己加上的导致出错的地方:

const QMetaObject DerivedObject::staticMetaObject = {
    { &A::staticMetaObject, qt_meta_stringdata_DerivedObject,
      qt_meta_data_DerivedObject, &staticMetaObjectExtraData }
};

注意第一个参数 &A::staticMetaObject,我们自己定义的类A是没有staticMetaObject着个成员的,这是QObject的宏展开之后才有的定义。此时如果把DerivedObject继承顺序更改一下:

class DerivedObject : public A,public QObject

其他部分保持不变,然后编译并输出:

const QMetaObject DerivedObject::staticMetaObject = {
    { &QObject::staticMetaObject, qt_meta_stringdata_DerivedObject,
      qt_meta_data_DerivedObject, &staticMetaObjectExtraData }
};

编译通过: }。

输出内存布局A和QObject的只是顺序对换,因为DerivedObject继承自A和QObject的关系没有改变,即使顺序改变,Q_OBJECT宏只有一个static变量不占类的内存。

以上,继承QObject并加入Q_OBJECT宏的时候,QT环境下在编译的时候会以第一个继承的对象(模板?)来生成对应的moc文件,如果带有Q_OBJECT宏,必须把QObject放在第一个继承的位置。
 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值