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

C++ 无法从指向基类的指针转换为指向派生类的指针,c++,qt,signals-slots,C++,Qt,Signals Slots,在标题中: 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()

在标题中:

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();
}
我想给你看看新钟。但当我编译时,错误是“无法通过虚拟基“时钟”将指向基类“QObject”的指针转换为指向派生类“ElecClock”的指针。”

错误发生在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);
}
void ElecClock::qt\u static\u metacall(QObject*\u o,QMetaObject::Call\u c,int\u id,void**a)
{
if(_c==QMetaObject::InvokeMetMethod){
ElecClock*\u t=static\u cast(\u o);//此行
Q_未使用(_t)
开关(_id){
案例0:_t->showTime();中断;
违约:;
}
}
Q_未使用(_a);
}
如何解决这个问题?我的构造函数和插槽有什么问题吗?
^

static\u cast
这样做:静态cast被称为static,因为对强制转换所需内容的计算是在编译时完成的,无论是指针算术还是转换

然而,当虚拟继承存在时,事情就变得有点困难了。主要问题是,通过虚拟继承,所有子类共享子对象的同一个实例。为此,
ElecClock
将有一个指向``的指针,而不是
Clock
正确的指针,并且
Clock
基类对象将在
ElecClock
之外实例化

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

解决方案

您需要
RTTI
(运行时类型信息),而将RTTI用于强制转换是
dynamic\u cast
的工作

安全性

static_cast
只要不变量保持不变,从基到派生的转换是安全的。否则,结果是
未定义的行为
。然而,在大型代码库的大部分上强制执行的不变量很少保持不变


>在使用相似的情况下,使用<代码> STATICE-CAST 时,请考虑使用<代码> AsScript(DyrimixCasic(…))< /P> > .< /P> < P>此问题来自下面的连接。由于

dynamic_cast
的工作速度较慢,自动生成的
qt_static_metacall
函数使用了
static_cast
,在多重继承的情况下无法进行强制转换

ElecClock::ElecClock(QWidget*parent):
时钟(家长)
{
......
--->连接(计时器、信号(超时())、此、插槽(显示时间());
......
}


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

请记住,作为运行时构造
dynamic\u cast
可能会失败。所以在使用强制转换的结果之前,不要忘记检查
nullptr
。@JesperJuhl,是的!我如何判断对象的动态类型和静态类型是否相同?很难说在这种情况下,连接对NewClock不起作用。如果您想使用带计时器的ElecClock,可以这样做应用程序a(argc,argv);//新时钟c;电子锁c;c、 connect();c、 show();返回a.exec();`其中connect函数封装connect部分。