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

二次信任 提交于 2021-01-28 07:42:00

问题


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

In source files:

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

In main.cpp:

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

    return a.exec();
}

I want to show the NewClock. But when i compile, the error is "cannot convert from pointer to base class 'QObject' to pointer to derived class 'ElecClock' via virtual base 'Clock'."

The error happens in 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);
}

How to solve this problem? Is there anything wrong in my constructors and slots? ^


回答1:


The problem comes from connection below. As dynamic_cast is working slower the automatically generated qt_static_metacall function used static_cast which is not able to cast in case of multiple inheritance

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

As solution I just can advice to encapsulate connection into function and call the function only if dynamic and static types of object are same. Otherwise you have to remove that line or refuse from multiple inheritance.




回答2:


static_cast do this: a static cast is dubbed static because the computation of what is necessary for the cast is done at compile-time, be it pointer arithmetic or conversions.

However, when virtual inheritance exists things become a bit more difficult. The main issue is that with virtual inheritance all subclasses share a same instance of the subobject. In order to do that, ElecClock will have a pointer to a ``, instead of a Clock proper, and the Clock base class object will be instantiated outside of ElecClock.

Although, it's impossible at compilation time to be able to deduce the necessary pointer arithmetics. It depends on the runtime type of the object.

Solution

You need RTTI (RunTime Type Information), and making use of RTTI for casts is the job of dynamic_cast.

Safety

static_cast from base to derived is safe so long as the invariant holds. Otherwise the result is undefined behavior. However invariants enforced over wide portions of large code bases rarely stay held.

So when using static_cast in the similar cases, consider putting assert(dynamic_cast<...>(...)) before.



来源:https://stackoverflow.com/questions/43897750/cannot-convert-from-pointer-to-base-class-to-pointer-to-derived-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!