2011-12-22 16 views
5

मैं एक गतिशील सरणी को लागू करने की कोशिश कर रहा हूँ: जब इस तरह इस्तेमाल किया, यह काम करता है के रूप में उम्मीद,दो आयामी सरणी का उपयोग कर टेम्पलेट्स

template <typename Item> 
class Array { 
private: 
    Item *_array; 
    int _size; 
public: 
    Array(); 
    Array(int size); 
    Item& operator[](int index); 
}; 

template <typename Item> 
Array<Item>::Array() { 
    Array(5); 
} 

template <typename Item> 
Array<Item>::Array(int size) { 
    _size = size; 
    _array = new Item [size]; 

    for (int i = 0; i < size; i++) 
     cout << i << " " << _array[i] << " " << &_array[i] << endl; 
} 

template <class Item> 
Item& Array<Item>::operator[](int index) { 
    if (index < 0 || index > _size-1) 
     cout << "this: " << this << ". Index out of range" << endl; 

    return _array[index]; 
} 

यानी प्रिंट 5:

Array<int> testArray(5); 
testArray[0] = 5; 
cout << testArray[0] << endl; 

हालांकि, मैं करूंगा एक द्वि-आयामी गतिशील सरणी के लिए कक्षा का उपयोग करना पसंद है। मैंने सोचा कि निम्नलिखित जादूगर रूप से काम करेगा और 5 प्रिंट करेगा ...

Array< Array<int> > testArray(5); 
testArray[0][0] = 5; 
cout << testArray[0][0] << endl; 

... लेकिन यह काम नहीं करता है। जब मैं मान को सेट करने की कोशिश करता हूं तो यह क्रैश होता है [0] [0]। डीबगर मुझे दिखाता है कि this में _size 0 और _array से NULL पर सेट है। उस बिंदु पर this अंतिम निर्मित ऐरे उदाहरण के _array के पहले तत्व को इंगित करता है।

उन चीजों में से एक जो मुझे नहीं मिलता है वह तब होता है जब "आंतरिक" सरणी इसके कन्स्ट्रक्टर को कॉल करती है। कोड के माध्यम से कदम, मुझे लगता है कि Array(int size) को एक बार और Array() पांच बार कहा जाता है। मैं एक विशिष्ट आकार के साथ आंतरिक सरणी बनाना चाहता हूं, लेकिन Array< Array<int>(10) > testArray(5) का उपयोग संकलित नहीं करता है।

क्या आप मुझे इस पर कुछ अंतर्दृष्टि प्रदान कर सकते हैं? ऐसा लगता है कि मैं अभी तक अपने सिर को टेम्पलेट्स के चारों ओर लपेट नहीं सकता ...

उत्तर

6

आप सी ++ में चेन कंस्ट्रक्टर कॉल नहीं कर सकते हैं। आपका पहला कन्स्ट्रक्टर कार्यान्वयन कुछ भी नहीं करता है, इसलिए माता-पिता Array में निहित 5 उदाहरण अनियमित होने के बाद समाप्त होते हैं, जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है।

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

संपादित: कारण है कि पहले निर्माता कुछ नहीं करता है लाइन

Array(5) 

वर्तमान उदाहरण के निर्माता फोन नहीं है, लेकिन बजाय एक नया (बेनाम) अस्थायी Array उदाहरण आबंटित करता है, कि जो लाइन के अंत में तुरंत नष्ट हो गया है।

+0

ओह, मुझे नहीं पता था कि आप चेन कंस्ट्रक्टर कॉल नहीं कर सकते! अब मैंने एक निजी फ़ंक्शन बनाया है और यह अब काम करता है, लेकिन केवल डिफ़ॉल्ट कन्स्ट्रक्टर में निर्दिष्ट आकार के साथ। गतिशील आकार के साथ आंतरिक सरणी बनाने के तरीके पर कोई विचार? – fabian789

+0

यदि आप सी ++ 11 ** और ** का उपयोग कर रहे हैं तो बाहरी सरणी आकार स्थिर रूप से ज्ञात है, तो आप सभी आंतरिक सरणी के लिए प्रारंभकर्ता प्रदान करने के लिए प्रारंभकर्ता सूची का उपयोग कर सकते हैं। वैसे भी, मैं इसे अपने उत्तर में लिखना भूल गया, लेकिन जब तक कि यह व्यायाम के अलावा कुछ भी नहीं है, असली समाधान 'std :: vector' का उपयोग करना है। –

+0

हां, यह सिर्फ एक अभ्यास है। क्या आप मुझे बता सकते हैं कि "प्रारंभकर्ता सूची" के साथ आपका क्या मतलब है? '_array = नई वस्तु [आकार] (आकार) का उपयोग करके; 'मेरे लिए संकलित नहीं करता है। उदाहरण के लिए – fabian789

3

डिफ़ॉल्ट मान का उपयोग निर्माता तर्क के बिना यह कॉल करने के लिए अर्थात Array(int index = 5);

कृपया चेक करें: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3

इस वस्तु को प्रारंभ करने के लिए एक वर्ग कॉल एक ही कक्षा की एक और निर्माता में से एक निर्माता कर सकते हैं?

+0

लिंक के लिए धन्यवाद! – fabian789

1

आप अपने डिफ़ॉल्ट सीटीआर से एक और सीटीओ नहीं कॉल कर सकते हैं। यदि आप एक डिफ़ॉल्ट मान चाहते हैं तो आप दोनों को एक साथ जोड़ सकते हैं।

template <typename Item> 
Array<Item>::Array(int size = 5) { 
    _size = size; 
    _array = new Item [size]; 

    for (int i = 0; i < size; i++) 
     cout << i << " " << _array[i] << " " << &_array[i] << endl; 
} 

हालांकि आप अभी भी दो ctor के लिए तो आप एक निजी _setup समारोह है कि इस तरह दोनों से इस्तेमाल किया जा सकता करने के लिए कार्यान्वयन स्थानांतरित कर सकते हैं पसंद करते हैं।

template <typename Item> 
Array<Item>::Array() { 
    _setup(5); 
} 

template <typename Item> 
Array<Item>::Array(int size) { 
    _setup(size); 
} 

template <typename Item> 
void Array<Item>::_setup(int size) { 
    _size = size; 
    _array = new Item [size]; 

    for (int i = 0; i < size; i++) 
     cout << i << " " << _array[i] << " " << &_array[i] << endl; 
} 

नए सरणी के लिए अमान्य प्रारंभकर्ता को हटाने के लिए संपादित किया गया।

+0

[]) जोड़ने के बाद [] ब्रैकेट मेरे लिए संकलित नहीं है ...? – fabian789

+0

तो ऐसा लगता है कि मैं अपने आप से आगे हो गया हूं और भूल गया हूं कि आप नए कथन के साथ सरणी के लिए प्रारंभकर्ता निर्दिष्ट नहीं कर सकते हैं। शायद एक सरणी के सूचक के बजाय वेक्टर का उपयोग करना आदर्श होगा। मुझे लगता है कि कक्षा के लिए और आप किसी भी मौजूदा एसएलएल का उपयोग नहीं कर सकते हैं। – jbreiding

+0

हां यह सिर्फ एक अभ्यास है :) – fabian789

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