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

时间:2017-05-10 16:10:27

标签: c++ qt signals-slots

标题:

this.instanceMethod1()

在源文件中:

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
......
}

在main.cpp中:

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()));
......
}

我想展示NewClock。但是当我编译时,错误是“无法通过虚拟基础'Clock'将指针转换为基类'QObject'指向派生类'ElecClock'。”

错误发生在moc_ElecClock.cpp中:

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

    return a.exec();
}

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

2 个答案:

答案 0 :(得分:2)

static_cast执行此操作:静态强制转换被称为静态,因为对于强制转换所需的内容的计算是在编译时完成的,无论是指针算术还是转换。

然而,当虚拟继承存在时,事情变得有点困难。主要问题是,使用虚拟继承,所有子类共享子对象的同一实例。为了做到这一点,ElecClock将指向一个``而不是Clock本身,而Clock基类对象将在ElecClock之外实例化。

虽然,在编译时不可能推断出必要的指针算术。它取决于对象的运行时类型。

<强>解决方案

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

<强>安全

只要不变量成立,从基数到派生的

static_cast是安全的。否则结果为undefined behavior。然而,在大部分大型代码库中强制执行的不变量很少保持不变。

因此,在类似情况下使用static_cast时,请考虑先放置assert(dynamic_cast<...>(...))

答案 1 :(得分:1)

问题来自下面的连接。由于dynamic_cast工作速度较慢,自动生成的qt_static_metacall函数使用了static_cast,在多重继承的情况下无法投射

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

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