2009-02-17 14 views
5

लिए काम नहीं करता जबनिर्माता एसटीडी से विरासत में मिली वर्ग :: स्ट्रिंग

#include <string> 

class MyString : public std::string 
{ 
public:  
    MyString() {} 
}; 

कर लेकिन नीचे उपयोग:

MyString s = "Happy day"; 
MyString s("Happy Day"); 
MyString s = (MyString)"Happy day"; 
न उनमें से

काम करता है।

ऐसा लगता है कि रचनाकारों/ऑपरेटरों की घोषणा/ओवरराइडिंग के साथ कुछ करने के लिए कुछ है, लेकिन क्या कोई यह इंगित करने में सहायता कर सकता है कि मुझे इन संसाधनों को कहां मिल सकता है?

धन्यवाद।

+0

जब आप वारिस करते हैं, तो आप बेस क्लास के गैर-डिफ़ॉल्ट नियंत्रकों को छुपाते हैं। यदि आप इन रचनाकारों को आमंत्रित करना चाहते हैं, तो आपको अपने उप-वर्ग में गैर-डिफ़ॉल्ट नियंत्रकों को परिभाषित करना होगा जो उन्हें आमंत्रित करते हैं। – ChrisW

+1

आपको std :: string से प्राप्त नहीं होना चाहिए। आप यह बता सकते हैं कि यह एक आभासी विनाशक नहीं है। आप खुद को कई संभावित समस्याओं तक खोल रहे हैं। Std :: स्ट्रिंग को सदस्य बनाएं। –

उत्तर

6

आप विभिन्न प्रकार है कि आप अपने स्ट्रिंग में रूपांतरित करने में सक्षम होना चाहते के लिए कुछ निर्माताओं को परिभाषित करने की जरूरत है। ये रचनाकार मूल रूप से अंतर्निहित std::string के माध्यम से पैरामीटर को सौंप सकते हैं।

आप मैन्युअल रूप से उन्हें बनाने नहीं है, तो आप के लिए एक संकलक default- और एक कॉपी-निर्माता बनाता है:

MyString() : std::string() { } 
MyString(const MyString &other) : std::string(other) { } 

स्ट्रिंग शाब्दिक से निर्माण की अनुमति देने के लिए, आप एक निर्माता है कि एक const char* लेता है की जरूरत है:

MyString(const char* other) : std::string(other) { } 

एक निर्माता है कि एक const std::string& लेता भी अपने स्ट्रिंग प्रकार के std::string रों कन्वर्ट करने के लिए उपयोगी होगा। आप सामान्य तार के अंतर्निहित रूपांतरण से बचना चाहते हैं, तो आप इसे explicit बनाना चाहिए:

explicit MyString(const std::string &other) : std::string(other) { } 

(संपादित क्योंकि मेरे मूल संस्करण त्रुटियों से भरा हुआ था और मैं स्वीकार किए जाते हैं जवाब नहीं हटा सकते हैं) नीचे

+0

कॉपी कन्स्ट्रक्टर प्रदान करने के लिए धन्यवाद। – purga

+0

मुझे 'MyString s ("हैप्पी डे")' और 'MyString s ("abc")' के बीच का अंतर नहीं दिखाई देता है। निश्चित रूप से आप गलत हैं। –

+0

ध्यान रखें कि यह संकलक को ओवरलोड को हल करते समय std :: स्ट्रिंग के लिए MyString को प्रतिस्थापित करने की अनुमति देता है।यह वही हो सकता है जो आप चाहते हैं, या भयानक भ्रम की ओर ले जाते हैं। मैंने दोनों मामलों को देखा है। –

1

आप एक ctor MyString को परिभाषित कर रहे हैं जिसमें कोई तर्क नहीं होता है। यदि अन्य ctors को ओवरराइड करता है, तो कोई स्ट्रिंग तर्क लेने वाला कोई सीटीओ नहीं है।

आप

MyString(const char * s): std::string(s){} 

तरह प्रकार const char * में से एक तर्क है, कुछ की ctor करने की जरूरत है (वाक्य रचना पर भरोसा है, उसे ढूंढने मत करो, मैं सी ++ हर दिन के किसी भी अब नहीं लिखते।)

C++ FAQ Lite on ctors में अनुभाग देखें।

(उफ़। कॉन्स्ट चार *, नहीं स्ट्रिंग। आप बताया कि मैं सी ++ हर दिन नहीं लिखा था।)

3

समस्या यह है कि आप निर्माता कि स्थिरांक चार * लेता ओवरलोड और आधार वर्ग कॉल करने की आवश्यकता निम्नानुसार निर्माता:

class MyString : public std::string { 
    public:  
     MyString() {} 
     MyString(const char* c) : std::string(c) {} 
}; 

आपके सभी तीन परीक्षणों को तब काम करना चाहिए।

3

std :: स्ट्रिंग को विरासत में प्राप्त करने का इरादा नहीं है। इसमें कोई वर्चुअल विधियां नहीं हैं ताकि आप इसकी किसी भी विधि को ओवरराइड नहीं कर सकें।

आपको रचना में देखना चाहिए। या बस उपयोगिता फ़ंक्शंस बनाना जो std :: स्ट्रिंग्स

34

std::string पर संचालित है, विरासत के लिए डिज़ाइन नहीं किया गया है। इसमें कोई आभासी फ़ंक्शन नहीं है (यहां तक ​​कि विनाशक भी नहीं!), ताकि आप कुछ भी ओवरराइड नहीं कर सकें। इसमें एक संरक्षित इंटरफ़ेस भी नहीं है, इसलिए आपको सबक्लासिंग से कुछ भी नहीं मिलता है कि आप कुछ स्टैंडअलोन उपयोगिता फ़ंक्शंस बनाकर नहीं प्राप्त कर सकते हैं जो std::string लेते हैं।

ध्यान रखें कि अधिकांश एसटीएल कार्यान्वयन आपको प्रति उम्मीदवारों के साथ std::string का उपयोग करने की उम्मीद करते हैं, संदर्भ अर्थशास्त्र नहीं, और यह विरासत वाले क्षेत्रों को जोड़ने या यहां तक ​​कि कमजोर कार्यों को ओवरराइड करने का मामला भी बनाता है।

तुम सच में अतिरिक्त कार्यों के साथ std::string की तरह कुछ चाहते हैं, तो आप उत्तराधिकार के बजाय रचना उपयोग करने पर विचार कर सकता है, लेकिन यह या तो महान नहीं है। आपको std::string विनाशक के बारे में चिंता करने की ज़रूरत नहीं है, जिसे आप ठीक से नहीं बुला रहे हैं, लेकिन आप std::string से कई विधियों को लपेटने के लिए तैयार हैं जो आपको चाहिए, जो कठिन है। साथ ही, आपके उपयोगिता फ़ंक्शन केवल MyString के साथ काम करेंगे जब अधिकांश कोड std::string की अपेक्षा करने जा रहे हैं, इसलिए यह बहुत पुन: प्रयोज्य नहीं है।

आप कुछ उपयोगिता कार्यों को बनाने से बेहतर हैं जो std::string लेते हैं।या, यदि std::string आपको जो चाहिए वह प्रदान नहीं कर रहा है, तो आपको अपनी ज़रूरतों के अनुरूप कुछ अन्य स्ट्रिंग कार्यान्वयन के साथ जाना चाहिए। यहां कुछ संभावनाएं हैं जो ध्यान में आती हैं:

  • एसजीआई का एसटीएल एक्सटेंशन, std::rope। यह जीएनयू सी ++ में है, तो शायद आप इस पर भरोसा कर सकते हैं।
  • Boost में एक बहुत व्यापक string algorithm library है जो आपको how your string is represented निर्दिष्ट करने के लिए अवधारणाओं का उपयोग करने देता है।
  • इसके अलावा एसटीडी से इस if you must "derive" :: स्ट्रिंग देख
+0

बेशक आप इससे प्राप्त कर सकते हैं। आपको बस यह सुनिश्चित करना होगा कि संकलन समय पर इसका समाधान योग्य हो। –

+0

मैंने आपको नहीं कहा ** ** इसे प्राप्त नहीं कर सका। बस इतना है कि आप ऐसा करके थोड़ा लाभ प्राप्त करते हैं। – tgamblin

+0

@ चार्ली: आप * कर सकते हैं *, यह आपको कुछ भी नहीं खरीदता है क्योंकि आप कुछ भी अधिभारित नहीं कर सकते हैं। आप उपयोगिता कार्यों को बंद करने से बेहतर हैं जो std :: स्ट्रिंग के तरीकों का उपयोग करते हैं। –

4

लाइन यह है कि आपको यह नहीं करना चाहिए। std::string पर विनाशक आभासी नहीं है। इसका मतलब यह है कि यदि आप निम्न कार्य करें:

std::vector<std::string*> s_vector; 
s_vector.push_back(new MyString("Hello")); 
s_vector.push_back(new std::string("World")); 

const std::vector<std::string*>::iterator s_vector_end = s_vector.end(); 
std::vector<std::string*>::iterator s = s_vector.begin(); 
for (; s != s_vector_end; ++s) 
{ 
    delete *s; // Error, MyString's destructor will 
       // not be called, but std::string's! 
} 

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

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