无法从指向基 class 的指针转换为指向派生 class 的指针

Cannot convert from pointer to base class to pointer to derived class

在headers中:

class Clock : public QWidget
{
    Q_OBJECT
public:
    explicit Clock(QWidget *parent = 0);
......
}

class ElecClock : virtual public Clock
{
    Q_OBJECT
public:
    explicit ElecClock(QWidget *parent = 0);
private slots:
    void showTime();  //display two LCDNumber
......
}

class MechClock : virtual public Clock
{
    Q_OBJECT
public:
    explicit MechClock(QWidget *parent = 0);
......
}

class NewClock : public MechClock, public ElecClock  //combination of Mechclock and ElecClock
{
    Q_OBJECT
public:
    explicit NewClock(QWidget *parent = 0);
private slots:
    void showTime(); //display two LCDNumber
......
}

在源文件中:

Clock::Clock(QWidget *parent) :
    QWidget(parent)
{
......
}

ElecClock::ElecClock(QWidget *parent) :
    Clock(parent)
{
......
connect(timer, SIGNAL(timeout()), this, SLOT(showTime()));
......
}

MechClock::MechClock( QWidget *parent) : 
    Clock(parent)
{
......
}

NewClock::NewClock(QWidget *parent) :
    MechClock(parent), ElecClock(parent), Clock(parent)
{
......
connect(timer, SIGNAL(timeout()), this, SLOT(showTime()));
......
}

在main.cpp中:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    NewClock c;
    c.show();

    return a.exec();
}

我想展示NewClock。但是当我编译时,错误是 "cannot convert from pointer to base class 'QObject' to pointer to derived class 'ElecClock' via virtual base 'Clock'."

错误发生在moc_ElecClock.cpp:

void ElecClock::qt_static_metacall(QObject *_o, QMetaObject::Call _c,int _id, void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        ElecClock *_t = static_cast<ElecClock *>(_o); // this line
        Q_UNUSED(_t)
        switch (_id) {
        case 0: _t->showTime(); break;
        default: ;
        }
    }
    Q_UNUSED(_a);
}

如何解决这个问题?我的构造函数和插槽有什么问题吗? ^

static_cast 这样做:静态转换被称为静态,因为转换所需的计算是在 编译时 完成的,无论是指针算法或转化。

然而,当虚拟继承存在时,事情就变得有点困难了。主要问题是,对于虚拟继承,所有子classes 共享同一个子对象实例。为了做到这一点,ElecClock 将有一个指向 `` 的指针,而不是 Clock 本身,并且 Clock 基础 class 对象将在 ElecClock.

尽管如此,在编译时不可能推导出必要的指针算法。这取决于对象的运行时类型。

解决方案

您需要 RTTI(运行时类型信息),使用 RTTI 进行转换是 dynamic_cast 的工作。

安全

static_cast 从基到派生是安全的,只要不变量成立。否则结果为 undefined behavior。然而,对大型代码库的广泛部分强制执行的不变量很少保持不变。

所以在类似情况下使用static_cast时,考虑把assert(dynamic_cast<...>(...))放在前面。

问题来自下面的连接。由于 dynamic_cast 运行速度较慢,因此使用了自动生成的 qt_static_metacall 函数 static_cast 在多重继承的情况下无法转换

ElecClock::ElecClock(QWidget *parent) : Clock(parent) { ...... ---> connect(timer, SIGNAL(timeout()), this, SLOT(showTime())); ...... }

作为解决方案,我只能建议将连接封装到函数中,并且仅当对象的动态和静态类型相同时才调用该函数。否则,您必须删除该行或拒绝多重继承。