【问题标题】:Cannot convert from pointer to base class to pointer to derived class无法从指向基类的指针转换为指向派生类的指针
【发布时间】:2017-05-10 16:10:27
【问题描述】:

在标题中:

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。但是当我编译时,错误是“无法通过虚拟基类'Clock'从指向基类'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);
}

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

【问题讨论】:

    标签: c++ qt signals-slots


    【解决方案1】:

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

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

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

    解决方案

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

    安全

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

    所以在类似情况下使用static_cast时,请考虑将assert(dynamic_cast&lt;...&gt;(...))放在前面。

    【讨论】:

    • 请记住,作为运行时构造 dynamic_cast 可能会失败。所以在使用转换结果之前不要忘记检查nullptr
    • @JesperJuhl,没错!
    【解决方案2】:

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

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

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

    【讨论】:

    • 如何判断对象的动态和静态类型是否相同?
    • 在这种情况下很难说,NewClock 的连接不起作用,如果你想使用带计时器的 ElecClock,你可以这样做。 ` QApplication a(argc, argv); // 新时钟 c;电子时钟 c; c.connect(); c.show(); return a.exec();` 其中connect函数封装了connect部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 2015-08-12
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多