2009-04-10 13 views
6

मैं प्रश्न सूचक के बजाय सूचक के संदर्भ में पारित करके here उल्लेख इस तरह सूचक को जवाब देने के लिए कोशिश कर रहा था:व्युत्पन्न * से बेस * & में कनवर्ट कर रहा

class Parent 
{ 
}; 

class Child : public Parent 
{ 
}; 

void RemoveObj(Parent*& pObj) 
{ 
    delete pObj; 
    pObj = NULL; 
} 

int main() 
{ 
    Parent* pPObj = new Parent; 
    Child* pCObj = new Child; 
    pPObj = new Parent(); 
    pCObj = new Child(); 



    RemoveObj(pPObj); 
    RemoveObj(pCObj); // This is line 32 
    return 1; 
} 

लेकिन इस पर निम्न संकलक त्रुटि पैदा करता है लाइन 32:

त्रुटि C2664: 'RemoveObj': नहीं कर सकते परिवर्तित से पैरामीटर 1 'बाल *' करने के लिए 'जनक * &'

मैं मानता हूं कि बाल ** से माता-पिता ** में रूपांतरण की अनुमति नहीं है। लेकिन इस रूपांतरण की अनुमति क्यों नहीं है?

+0

का संग्रह क्यों नहीं है; मुख्य() के अंत में? क्या यह 0 वापस नहीं होना चाहिए; ? – DeadHead

+0

मैंने बस लिंक किए गए प्रश्न से कोड चिपकाया है लेकिन यह – Naveen

+0

प्रश्न से संबंधित नहीं है, मुझे पता है कि यह वास्तव में प्रश्न से संबंधित नहीं था। सोचने के साथ संयुक्त जिज्ञासा मेरे ज्ञान में कुछ अंतर हो सकता है। – DeadHead

उत्तर

7

प्रकार का एक ऑब्जेक्ट Parent*& पर बाध्य नहीं किया जा सकता है, उसी कारण से Child** को Parent** में परिवर्तित नहीं किया जा सकता है। यह अनुमति देने से प्रोग्रामर (जानबूझकर या नहीं) को बिना किसी कलाकार के प्रकार को तोड़ने की अनुमति मिल जाएगी।

class Animal {}; 

class DangerousShark : public Animal {}; 

class CuteKitten : public Animal {}; 

void f(Animal*& animalPtrRef, Animal* anotherAnimalPtr) 
{ 
    animalPtrRef = anotherAnimalPtr; 
} 

void g() 
{ 
    DangerousShark myPet; 
    CuteKitten* harmlessPetPtr; 

    f(harmlessPetPtr, &myPet); // Fortunately, an illegal function call. 
} 

संपादित

मुझे लगता है कि भ्रम की स्थिति से कुछ शब्द 'कन्वर्ट' और 'रूपांतरण' के ढीले प्रयोग की वजह से पैदा होती है कि।

संदर्भ पुन: असाइन नहीं किया जा सकता है, वस्तुओं के विपरीत जिन्हें पुन: असाइन किया जा सकता है, इसलिए जब हम रूपांतरण की बात करते हैं तो संदर्भों के संदर्भ में हम केवल एक नया संदर्भ शुरू करने के बारे में चिंतित हो सकते हैं।

संदर्भ हमेशा किसी ऑब्जेक्ट से बंधे रहते हैं, और ओपी के प्रश्न से यह स्पष्ट था कि वह एक ऐसा संदर्भ प्राप्त करने का लक्ष्य रख रहा है जो मौजूदा वस्तु से सीधे बंधे हो। यह केवल तभी अनुमति दी जाती है जब संदर्भ को प्रारंभ करने के लिए उपयोग किया गया ऑब्जेक्ट संदर्भ के प्रकार के साथ संदर्भ-संगत है। अनिवार्य रूप से, यह केवल तभी होता है जब प्रकार समान होते हैं, या वस्तु का प्रकार संदर्भ के प्रकार से लिया गया है और संदर्भ प्रकार कम से कम सीवी-योग्य प्रारंभिक वस्तु के रूप में योग्य है। विशेष रूप से, विभिन्न प्रकार के पॉइंटर्स संदर्भ-संगत नहीं हैं, भले ही प्रकार के संबंधों के संबंध में।

अन्य मामलों में, संदर्भ को किसी संदर्भ के साथ प्रारंभ किया जा सकता है जिसे संदर्भ प्रकार में परिवर्तित किया जा सकता है। इन मामलों में, हालांकि, संदर्भ होना चाहिए और अस्थिर नहीं होना चाहिए और रूपांतरण अस्थायी बना देगा और संदर्भ इस अस्थायी और मूल वस्तु से बंधे नहीं होगा। जैसा कि बताया गया है, यह ओपी के प्रेरक उदाहरण की आवश्यकताओं के लिए उपयुक्त नहीं है।

सारांश में, एक Child सीधे एक Parent& करने के लिए बाध्य किया जा सकता है, लेकिन एक Child* सीधे एक Parent*& करने के लिए बाध्य नहीं किया जा सकता। Parent* const& को Child* के साथ प्रारंभ किया जा सकता है, लेकिन संदर्भ वास्तव में Child* ऑब्जेक्ट से प्रारंभिक अस्थायी Parent* ऑब्जेक्ट प्रतिलिपि से जुड़ जाएगा।

+0

उदाहरण के लिए धन्यवाद, अब यह स्पष्ट है। – Naveen

+0

@ चार्ल्स बेली: काफी कुछ मुद्दे: [1] प्यारा बिल्ली के बच्चे के लिए सही डाटर नहीं कहा जाएगा क्योंकि पशु के लिए डॉक्टर आभासी नहीं है। [2] हानिरहित पीआरटी अनिर्धारित है। – dirkgently

+0

धन्यवाद, मैंने हानिकारक के लिए हानिरहित बदल दिया आखिरी पल पर लेकिन केवल एक ही स्थान पर। मेरे उदाहरण में कोई डिलीट नहीं चल रहा है इसलिए मुझे यकीन नहीं है कि आपका बिंदु [1] कैसे लागू होता है। –

4
  • आपके कक्षाओं में वर्चुअल फ़ंक्शन नहीं है। देखें FAQ 20.7

  • Parent *& वजह से एक Parent वस्तु के लिए एक सूचक के लिए एक संदर्भ है। आप Child पर पॉइंटर पास कर रहे हैं - ये असंगत प्रकार हैं। आप एक स्थिरांक-संदर्भ अर्थात के लिए एक अस्थायी बाध्य कर सकते हैं यदि आप करने के लिए अपने मानदंड को बदलना:

    void RemoveObj(Parent* const& foo);

लेकिन तब आप इस के साथ ज्यादा ऐसा करने में सक्षम नहीं होगा।

यह सिर्फ एक परीक्षण कोड था इसलिए मैंने कोई वर्चुअल विनाशक नहीं बनाया। अगर मैं RemoveObj() की दूसरी कॉल में सही ढंग से समझता हूं, तो मुझे एक अस्थायी अभिभावक * ऑब्जेक्ट मिलता है जिसे फ़ंक्शन के कॉन्स्ट संदर्भ के रूप में पारित किया जा सकता है। क्या ये सही है?

मैं दृढ़ता से सुझाव है कि आप फिर से एक बार में के रूप में मानक सी ++ 98 मोड में निम्न कार्यक्रम चलाने के लिए, और उसके बाद के बाद आप बाहर foo(b) और uncommented delete b टिप्पणी की है। इसके बाद, ~s() से पहले virtual डालने का प्रयास करें। अंतर आत्म-व्याख्यात्मक होना चाहिए!

#include <iostream> 
using namespace std; 
struct s { 
    s() {cout << __func__ << endl; } 
    ~s() {cout << __func__ << endl; } 
}; 

struct t : s { 
    t() {cout << __func__ << endl; } 
    ~t() {cout << __func__ << endl; } 
}; 

void foo(s* const& x) { delete x; } 

int main() { 
t* b = new t; 
foo(b); 
//delete b; 
} 
+0

यह सिर्फ एक परीक्षण कोड था इसलिए मैंने कोई वर्चुअल विनाशक नहीं बनाया। अगर मैं RemoveObj() की दूसरी कॉल में सही ढंग से समझता हूं, तो मुझे एक अस्थायी अभिभावक * ऑब्जेक्ट मिलता है जिसे फ़ंक्शन के कॉन्स्ट संदर्भ के रूप में पारित किया जा सकता है। क्या ये सही है? – Naveen

0

प्रकार * & तरह की दूसरी वाक्यात्मक प्रपत्र ** और जनक * & एवं बाल * & असंबंधित एक दूसरे के रूप में अच्छी तरह जनक ** एवं बाल रूप में ** होते हैं - इन विभिन्न प्रकार एक वर्ग में नहीं हैं पदानुक्रम।

0

यह डिर्क द्वारा उल्लिखित कारणों के लिए काम नहीं करेगा। क्या तुम सच में एक RemoveObj विधि की जरूरत है तो मैं बस एक जनक * के रूप में अपनी नई आवंटित बाल वस्तु की बचत होगी:

#include <iostream> 

class Parent 
{ 
public: 
    virtual ~Parent() 
    { 
     std::cout << "Parent destructor" << std::endl; 
    } 
}; 

class Child : public Parent 
{ 
public: 
    virtual ~Child() 
    { 
     std::cout << "Child destructor" << std::endl; 
    } 
}; 

void RemoveObj(Parent*& pObj) 
{ 
    delete pObj; 
    pObj = NULL; 
} 



int main (int argc, const char * argv[]) { 

    Parent* pPObj = new Parent; 
    Parent* pCObj = new Child; 

    RemoveObj(pPObj);  
    RemoveObj(pCObj); // This is line 32 


    return 0; 
} 
+0

हां, हाथ से ऐसा करना (कोई अंतर्निहित रूपांतरण नहीं) काम करता है। –

1

आप एक Child* to a Parent* परिवर्तित कर सकते हैं: यह एक अस्थायी पैदा करता है। लेकिन आप उस अस्थायी के लिए एक गैर-कॉन्स्ट संदर्भ को बाध्य नहीं कर सकते हैं।

यह **/*&/etc की कोई समस्या नहीं है। आप जो करने की कोशिश कर रहे हैं वह बिल्कुल ठीक है और समझ में आता है। शार्क बनाम बिल्ली का बच्चा एक ही मुद्दा है: बिल्ली का बच्चा और शार्क मिश्रण करने की बात नहीं। आप उस अज्ञात सूचक के गैर-कॉन्स्ट संदर्भ को बाध्य नहीं कर सकते हैं।

यह Parent** vs. Child** समस्या नहीं है: वहाँ है, अगर एक Child** एक Parent** था, तो एक p[0] = new NotAChild; आवंटित कर सकते हैं। ऑब्जेक्ट्स का संग्रह जो ए के सभी उपप्रकार हैं ए

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