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部分。