2013-08-15 8 views
6
class Base 
{ 
public: 
    void operator()() { func(); } 
private: 
    virtual void func() {} 
}; 

class Derived1 : public Base 
{ 
private: 
    void func() override {/*do something*/} 
}; 

class Derived2 : public Base 
{ 
private: 
    void func() override {/*do something else*/} 
}; 

साथ प्रारंभ क्योंकि मैं ऑपरेटर ओवरलोडिंग उपयोग करना चाहते हैं,
संदर्भ सूचक की तुलना में एक बेहतर विकल्प है।सी ++ आधार वर्ग संदर्भ अलग व्युत्पन्न वर्ग वस्तु

मैं क्या करने का इरादा की तरह है:

if (condition) { 
    Base& obj = Derived1(); 
} else { 
    Base& obj = Derived2(); 
} 

लेकिन obj को नष्ट कर दिया और गुंजाइश के अंत हो जाएगा।

Base& obj; 
if (condition) { 
    obj = Derived1(); 
} else { 
    obj = Derived2(); 
} 

या तो काम नहीं करेगा,
क्योंकि संदर्भ घोषणा पर प्रारंभ करने की आवश्यकता है।

अगर मैं कोशिश:

Base& obj = condition ? 
    Derived1() : Derived2(); 

फिर भी एक त्रुटि, त्रिगुट ऑपरेटर परिवर्तनीय प्रकार की उम्मीद क्योंकि।

इस समस्या से निपटने के लिए सबसे अच्छा समाधान क्या है?

उत्तर

4

आप इस मामले में ?: का उपयोग नहीं कर सकते हैं क्योंकि Derived1 और Derived2 विभिन्न प्रकार हैं।

एक संभव तरीका सूचक का उपयोग करना है, इस मान्य है:

condition ? pObj.reset(new Derived1()) : pObj.reset(new Derived2()); 

या

#include <memory> 
std::unique_ptr<Base> pObj; 
if (condition) 
{ 
    pObj.reset(new Derived1()); 
} 
else 
{ 
    pObj.reset(new Derived2()); 
} 

आप operator() इस तरह कह सकते हैं:

(*pObj)(); 
+0

सूचक उपयोग करने का अर्थ मैं> ऑपरेटर() obj- उपयोग करने के लिए, और ऑपरेटर ओवरलोडिंग के प्राकृतिक वाक्य रचना खो दिया है। – gnephiak

+0

मेरा अद्यतन उत्तर देखें, आपको 'कॉल करना नहीं है -> और यह – billz

+0

ऑपरेटर ओवरलोडिंग खो देता है हालांकि यह सूचक का उपयोग करता है, फिर भी मेरी आवश्यकता के लिए सबसे अच्छा जवाब है। – gnephiak

0

यह काम करेगा:

Base* obj; 
if (condition) { 
    obj = new Derived1; 
} else { 
    obj = new Derived2; 
} 

और फिर अपने कोड के अंत में आप एक

delete obj 
1

जोड़ने के लिए आप

Base *obj1; 
if (condition) { 
    obj1 = new Derived1(); 
} else { 
    obj1 = new Derived2(); 
} 
Base &obj = *obj1; 

नीचे के रूप में अपने कोड को संशोधित कर सकते हैं लेकिन करना है सुनिश्चित करें कि आप बाद में

1

अगर obj1 हटाना आप संदर्भ चाहते हैं, आप इसे अस्थायी रूप से बाध्य नहीं कर सकते हैं जब तक कि यह const Base & न हो।

Derived1 d1; 
Derived2 d2; 

हालांकि, आप (एक लैम्ब्डा सहित) एक समारोह के साथ एक गैर स्थिरांक संदर्भ प्राप्त कर सकते हैं: यह आपको एक वास्तविक वस्तु की जरूरत करने के लिए बाध्य है, तो के उस के साथ शुरू करते हैं का मतलब है। यदि लैम्ब्डा उपलब्ध नहीं हैं, तो सामान्य कार्य को d1 और d2 पैरामीटर के रूप में लेने की आवश्यकता होगी।

auto choose = [&](bool b) -> Base & { 
    if (b) {return d1;} 
    else {return d2;} 
}; 

अब obj पैदा कर रही है आसान:

Base &obj = choose(condition); 
+0

यह वास्तव में एक कामकाजी समाधान है, लेकिन अनावश्यक वस्तु के साथ। मैं बिलज़ के उत्तर को सही के रूप में स्वीकार करूंगा। – gnephiak

+0

@gnephiak, दुर्भाग्य से, मुझे नहीं लगता कि बिना किसी प्रकार के पॉइंटर के आसपास एक रास्ता है। मुझे लगता है कि आप तकनीकी रूप से एक स्मार्ट सूचक का उपयोग कर सकते हैं और 'बेस और obj = * ptr.get();' और फिर सुनिश्चित करें कि आप 'ptr' के दायरे से बाहर होने के बाद' obj' का उपयोग नहीं करते हैं। – chris

+0

यदि अनावश्यक वस्तु ठीक है (यह सब के बाद ढेर पर है), तो आप हैकी लैम्ब्डा के बजाय static_cast का उपयोग कर सकते हैं: 'बेस और obj = condition? static_cast (डी 1): static_cast <बेस &>(d2); ' – iano

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