2011-07-23 10 views
6

the QObject documentation और कई अन्य लोगों की व्याख्या है, QObject की पहचान है और इस प्रकार इसकी प्रतिलिपि निर्माता और असाइनमेंट ऑपरेटर को छुपाता है।सी ++ कॉपी और असाइनमेंट के साथ क्यूटी प्रतिबिंब

हालांकि, मैं इसकी गतिशील गुण सुविधा या संकेत/स्लॉट सुविधा के लिए QObject से प्राप्त नहीं कर रहा हूं। मैं केवल प्रतिबिंब, या Foo::staticMetaObject तक पहुंचने की क्षमता चाहता हूं।

class Foo : public QObject { 
    Q_OBJECT 
    Q_ENUMS(Color) 
public: 
    enum Color { Blue, Red, Pink }; 
private: 
    Color color; 
}; 

Q_DECLARE_METATYPE(Foo::Color) 

मैं तो कॉपी नहीं कर सकते Foo साथ:

Foo a; 
Foo b; 
a = b; 

इस मामले में कॉपी और काम की अनुमति के लिए सबसे अच्छा तरीका क्या है? क्या मुझे बिल्कुल एक कॉपी कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर लिखने की ज़रूरत है? वे क्या दिखेंगे? प्रतिबिंब अभी भी काम करेगा?

+0

आपका मतलब है कि 'QObject' का उपयोग नहीं करता है। क्योंकि प्रतिबिंब इस मुद्दे का स्रोत नहीं है। मुद्दा यह है कि QObject प्रतिलिपि बनाते हैं और असाइनमेंट निजी (एक अच्छे कारण के लिए)। –

+1

@ क्रिस्टियनप, अच्छा सुझाव, मैं इसे संपादित कर दूंगा * if * @alexisdm ने मेरे सटीक प्रश्न का सही उत्तर नहीं दिया। अक्सर बार जवाब होता है कि "जो भी आप करने के लिए कह रहे हैं वह मत करो" लेकिन इस मामले में, भले ही यह एक उचित उत्तर है, वही भी है जो मुझे ऐसा करने देता है जो मैं करना चाहता हूं: 'Q_GADGET' –

उत्तर

14

आप केवल के लिए

  • वर्ग के नाम प्रतिबिंब होने में रुचि रखते हैं,
  • enums और झंडे (Q_ENUMS, Q_FLAGS),
  • वर्ग की जानकारी (Q_CLASSINFO),

आप Q_GADGET instead of Q_OBJECT का उपयोग कर सकते हैं:

class Foo { 
    Q_GADGET 
    Q_ENUMS(Color) 
public: 
    enum Color { Blue, Red, Pink }; 
private: 
    Color color; 
}; 

जो Foo::staticMetaObject घोषित और परिभाषित करेगा।

+0

वाह, मैं पहले 'Q_GADGET' से नहीं सुना था। तो ऐसा लगता है कि यह 'Q_OBJECT' का हल्का और स्थैतिक संस्करण है जो कुछ मामलों (जैसे) में बहुत उपयोगी हो सकता है। दुख की बात है कि यह दस्तावेज नहीं है, कम से कम मुझे यह नहीं मिला। यह इसे अनौपचारिक बनाता है और इस प्रकार भविष्य में काम करने की गारंटी नहीं देता है :( – leemes

+0

@leemes वास्तव में 'QOOject' पृष्ठ पर 'Q_OBJECT' के साथ संक्षेप में उल्लेख किया गया है (मैंने उपरोक्त लिंक जोड़ा है)। लेकिन आप कह सकते हैं कि यह बहुत अच्छी तरह छुपा हुआ है, और मुझे कुछ और के लिए moc स्रोत कोड के माध्यम से खोजते समय केवल इसके बारे में पता चला। – alexisdm

1

मुझे qt के बारे में बहुत कुछ पता नहीं है, लेकिन अगर प्रतिलिपि बनाने की अनुमति नहीं है तो इसके लिए एक कारण होना चाहिए (जिस पर आपके द्वारा पोस्ट किए गए लिंक में चर्चा की गई है)। आप अपने डिजाइन को बदल नहीं सकते हैं।

फिर भी यदि आप जोर देते हैं तो memcpy आपका अंतिम उपाय हो सकता है। मैं इसे व्यक्तिगत रूप से अनुशंसा नहीं करता हूं, क्योंकि आपको गहरी प्रतिलिपि, vtable इत्यादि की देखभाल करना है जो हमेशा तुच्छ नहीं होते हैं।

2

आप निश्चित रूप से अपनी व्युत्पन्न कक्षा में एक कॉपी कन्स्ट्रक्टर और एक कॉपी असाइनमेंट ऑपरेटर दोनों को लागू कर सकते हैं, लेकिन यह संभवतः खराब डिज़ाइन का संकेत है। इस उदाहरण को लें:

#include <iostream> 

class Base { 
public: 
    Base() {} 

private: 
    Base(const Base& other) { 
     std::cout << "Base copy constructor invoked!" << std::endl; 
    } 
}; 

class Derived : public Base { 
public: 
    Derived() {} 

    Derived(const Derived& other) { 
     std::cout << "Derived copy constructor invoked!" << std::endl; 
    } 
}; 

int main(int argc, char** argv) { 
    Derived a; 
    Derived b = a; 

    return 0; 
} 

यह ठीक ठीक संकलित करेगा। हालांकि, जैसा कि अपेक्षित है, जब आप परिणामस्वरूप प्रोग्राम चलाते हैं, तो मुद्रित सभी Derived copy constructor invoked! है। जब बेस क्लास अपनी कॉपी कन्स्ट्रक्टर/कॉपी असाइनमेंट ऑपरेटर को निजी के रूप में घोषित करता है, जो व्युत्पन्न कक्षाओं को अपने संस्करणों को लागू करने से नहीं रोकता है। यह बस व्युत्पन्न कक्षाओं को बेस क्लास संस्करण पर कॉल करने से रोकता है।

और इसमें समस्या है: यह सुनिश्चित करने के लिए हमेशा अच्छा अभ्यास होता है कि आप किसी ऑब्जेक्ट के सभी हिस्सों की प्रतिलिपि बनाते हैं, ताकि आपके पास वास्तव में दो अलग-अलग प्रतियां हों। आपकी ऑब्जेक्ट का हिस्सा बेस क्लास के स्वामित्व वाले डेटा में शामिल है, इसलिए आपको यह सुनिश्चित करना होगा कि पूर्ण प्रतिलिपि बनाई गई हो, यह सुनिश्चित करने के लिए आपको बेस क्लास की कॉपी कन्स्ट्रक्टर/कॉपी असाइनमेंट ऑपरेटर का आह्वान करना चाहिए। लेकिन वह डेटा गैर-प्रतिलिपि डिजाइन द्वारा है। इस प्रकार, वस्तु के सभी भागों की प्रतिलिपि बनाना असंभव है।

यदि आप इस डिज़ाइन के साथ रहना चाहते हैं तो यह आपके ऊपर निर्भर करता है। खुद से पूछने के लिए एक महत्वपूर्ण बात यह है कि क्या आपकी व्युत्पन्न कक्षा को वास्तव में प्रतिलिपि बनाने की आवश्यकता है? यदि नहीं, तो चिंता करने की कोई बात नहीं है!

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