2015-03-11 4 views
5

निम्नलिखित कोड पूरी तरह से संकलित:QWbject के माता-पिता के रूप में QObject को मजबूर करने के क्या परिणाम हैं?

QObject* o = new QObject(0); 
QWidget* w = new QWidget(0); 
qobject_cast<QObject*>(w)->setParent(o); 

मैं नहीं कानूनी तौर पर QWidget की एक अभिभावक के रूप QObject सेट कर सकते हैं। लेकिन qobject_cast का उपयोग करना संभव है। क्या नकारात्मक नतीजे हैं?

+1

बस उत्सुक: इस तरह के पदानुक्रम का कारण क्या है? – vahancho

+3

क्या?! QWidget QObject –

+2

'QWidget :: setParent (QWidget *) 'छुपाएं' QObject :: setParent (QObject *) 'से सार्वजनिक रूप से विरासत में मिलता है। – Oktalist

उत्तर

9

क्यूटी को गैर-विजेट माता-पिता को QWidget पर समर्थन देने के लिए डिज़ाइन नहीं किया गया है। निजी तौर पर, मैं इस समय एक बिंदुहीन हैक के रूप में इसका इलाज करता हूं। यह संकलित होगा, लेकिन कभी काम नहीं करेगा। मैं इसे Qt में एक एपीआई बग मानता हूं, क्योंकि QWidget उस सीमा के कारण लिस्कोव प्रतिस्थापन सिद्धांत अर्थ में QObject पूरी तरह से नहीं है।

क्यूटी 4.x विजेट को सक्रिय करने का प्रयास करते समय क्रैश हो जाएगा। तो यह तब तक काम करेगा जब तक आप अपना आवेदन केंद्रित नहीं करते हैं और फिर क्रैश हो जाएंगे।

QObject::setParent() में क्यूटी 5.x आवेषण।

दावे को नजरअंदाज किया जा सकता है, हालांकि:

// https://github.com/KubaO/stackoverflown/tree/master/questions/widget-parent-28992276 
#include <QApplication> 
#include <QLabel> 

class ParentHacker : private QWidget { 
public: 
    static void setParent(QWidget * child_, QObject * parent) { 
     // The following line invokes undefined behavior 
     auto child = static_cast<ParentHacker*>(child_); 
     Q_ASSERT(child->d_ptr->isWidget); 
     child->d_ptr->isWidget = 0; 
     child->QObject::setParent(parent); 
     child->d_ptr->isWidget = 1; 
    } 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    QLabel w{"Hello!"}; 
    w.setMinimumSize(200, 100); 
    w.show(); 
    ParentHacker::setParent(&w, &app); 
    return app.exec(); 
} 

यह कहीं और तो दुर्घटना होगा।

आप क्यूटी को काम करने के लिए पैच करने की कोशिश कर रहे एक उग्र लड़ाई से लड़ेंगे। यह एक सार्थक लड़ाई नहीं है, मुझे लगता है - जब तक QWidget सचमुच QObject बनाने और उसके कन्स्ट्रक्टर हस्ताक्षर को बदलने के लिए कोई निर्णय नहीं लिया जाता है। यह क्यूटी 6 में जल्द से जल्द किया जा सकता है क्योंकि यह एक बाइनरी-असंगत परिवर्तन AFAIK है।

इसके अलावा, आप जो करने की कोशिश कर रहे हैं वह अधिकतर अनावश्यक है। आप निश्चित रूप से एक छिपे हुए QWidget माता-पिता को कई स्टैंड-अलोन टॉप-स्तरीय विजेट्स पर देख सकते हैं।

#include <QApplication> 
#include <QLabel> 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    QWidget parent; 
    QLabel l1{"Close me to quit!"}, l2{"Hello!"}; 
    for (auto label : {&l1, &l2}) { 
     label->setMinimumSize(200, 100); 
     label->setParent(&parent); 
     label->setWindowFlags(Qt::Window); 
     label->setText(QString("%1 Parent: %2."). 
        arg(label->text()).arg((quintptr)label->parent(), 0, 16)); 
     label->show(); 
    } 
    l2.setAttribute(Qt::WA_QuitOnClose, false); 
    return app.exec(); 
} 

विजेट छिपा होने के भूमि के ऊपर कम है, आप माता-पिता के लिए एक QWidget बजाय QObject एक के उपयोग करके किसी भी संसाधनों को बर्बाद नहीं कर रहे हैं।

संबंधित मुद्दे