2013-08-23 12 views
7

मान लीजिए कि मेरे पास foo नामक एक वर्ग है जिसे bar नामक कक्षा से प्राप्त किया गया है।std :: unique_ptr को std :: unique_ptr में एक सुपरक्लास में कनवर्ट करने का सही तरीका क्या है?

मेरे पास foo के उदाहरण के लिए std::unique_ptr है और मैं इसे उस फ़ंक्शन में पास करना चाहता हूं जो केवल std::unique_ptr<bar> लेता है। मैं सूचक को कैसे परिवर्तित कर सकता हूं ताकि यह मेरे कार्य में काम कर सके?

+0

है 'एक बहुरूपी उदाहरण foo'? – Mahesh

+2

कोई भी फ़ंक्शन बनाएं जो स्मृति से आया है या बाद में क्या होता है, इसके संदर्भ में पैरामीटर लें (या कच्चे सूचक अगर यह शून्य हो)। –

+1

@NeilKirk: यह कार्य फ़ंक्शन के लिए है, लेकिन संग्रह में 'unique_ptr ' स्टोर करने के लिए यह उचित उपयोग केस है। और यदि फ़ंक्शन को इसे स्टोर करना है ... –

उत्तर

27

आप एक std::unique_ptr<bar> करने के लिए एक std::unique_ptr<foo> rvalue परिवर्तित कर सकते हैं:

std::unique_ptr<foo> f(new foo); 
std::unique_ptr<bar> b(std::move(f)); 

जाहिर है, सूचक b के स्वामित्व की जाएगी और अगर bbar जरूरतों को नष्ट कर दिया जाता है एक virtual नाशक है।

-1

आप नहीं कर सकते हैं, क्योंकि यह सबसे बुनियादी unique_ptr नियम का उल्लंघन होगा: वहाँ केवल एक उदाहरण है कि किसी भी सूचक रखती हो, pointee है, और unique_ptr यह (के पूर्ण स्वामित्व है जब यह क्षेत्र से बाहर चला जाता है हटा दिया गया है)।

unique_ptr<T> और unique_ptr<U> (जहां U : T) जैसा कि आपने देखा है, संगत नहीं हैं।

shared_ptr, जिसके लिए आप अनेक उदाहरण हो सकते के लिए, वहाँ std::static_pointer_cast कि सिर्फ एक static_cast तरह बर्ताव करता है, सिवाय इसके कि यह एक shared_ptr स्वीकार करता है और एक और एक (और एक ही वस्तु के लिए दोनों बिंदु) रिटर्न है।

यदि आपको पूरी तरह से unique_ptr का उपयोग करने की आवश्यकता है, तो आपको एक ऐसा फ़ंक्शन बनाना होगा जो पहले आपके वर्तमान unique_ptr को अस्वीकार कर देगा और उस पॉइंटर को सही प्रकार के नए में डाल देगा। आपको अपने फ़ंक्शन कॉल के बाद विपरीत रूपांतरण करने की भी आवश्यकता हो सकती है।

+1

+1। पूर्णता के लिए, 'std :: dynamic_pointer_cast <>' और 'std :: const_pointer_cast <>' अन्य सामान्य सूचक रूपांतरणों के लिए मौजूद है। – justin

+3

बेशक आप कर सकते हैं, जाहिर है, आपको केवल स्वामित्व स्थानांतरित करना होगा। –

+0

@MatthieuM। "अगर आपको पूरी तरह से एक unique_ptr का उपयोग करने की आवश्यकता है, तो आपको एक ऐसा फ़ंक्शन बनाना होगा जो पहले आपके वर्तमान अद्वितीय_ptr को अस्वीकार कर देगा और उस पॉइंटर को सही प्रकार के नए में डाल देगा।" मेरा मुद्दा यह था कि 'unique_ptr ' 'unique_ptr ' संदर्भ से बाध्य नहीं हो सकता है। इस तरह स्वामित्व स्थानांतरित करना भी अपवाद-सुरक्षित नहीं है। – zneak

0

आप इस वाक्य विन्यास का उपयोग हो सकता है:

std::unique_ptr<parent> parentptr = std::unique_ptr<child>(childptr); 

या आप std::move उपयोग कर सकते हैं।

अन्य विकल्प कच्चे सूचक फेंकना है, लेकिन आप एक समारोह को बदलने की जरूरत:

void func(const parent* ptr) 
{ 
    // actions... 
} 
func(*childptr); 

यहाँ स्मार्ट संकेत के बारे में एक अच्छा लेख है और कार्यों के लिए इसे पारित: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters

2

विरासत की वजह से कुछ भी विशेष आवश्यक नहीं है। आप std::move उपयोग करने के लिए एक समारोह के लिए unique_ptr उत्तीर्ण करने की आवश्यकता है, लेकिन यह सच है, भले ही प्रकार से मेल खाते हैं:

#include <memory> 

struct A { 
}; 

struct B : A { 
}; 

static void f(std::unique_ptr<A>) 
{ 
} 

int main(int,char**) 
{ 
    std::unique_ptr<B> b_ptr(new B); 
    f(std::move(b_ptr)); 
} 
संबंधित मुद्दे