2012-11-27 26 views
12

आमतौर पर एक निरंतर सदस्य चर को परिभाषित करने से आप अपने वर्ग है, जो केवल एक गेटर लेकिन कोई सेटर है में एक निरंतर निजी सदस्य चर है जब, यह कुछ इस तरह दिखेगा:सी ++ वर्ग निर्माता अंदर

// Example.h 
class Example { 
    public: 
     Example(const int value); 
     const int getValue() const; 
    private: 
     const int m_value; 
}; 


// Example.cpp 
#include "Example.h" 

Example::Example(const int value) 
: m_value(value) 
{ 
} 

const int Example::getValue() const 
{ 
    return m_value; 
} 

अब क्या मैं ऐसा करने की कोशिश कर रहा हूं, उसके पास निरंतर int सदस्य चर है, लेकिन प्रारंभिक खंड में इसे परिभाषित करने की बजाय: : m_value(value) मुझे एक अन्य वस्तु लेने की आवश्यकता है - मैं इस उदाहरण में एक वेक्टर का उपयोग करूंगा - जैसा कि कन्स्ट्रक्टर का पैरामीटर, और पैरामीटर ऑब्जेक्ट के आधार पर m_value सेट करें।

Example::Example(std::vector<Example*> myVec) 
{ 
    if (myVec.size()) { 
     m_value = myVec.size() + 1; 
    } 
    else { 
     m_value = -1; 
    } 
} 

लेकिन मैं एक त्रुटि uninitialized member 'Example::m_value' with 'const' type 'const int' हो और अगर मैं m_value प्रारंभ करने के अंदर init: इस मामले में, मैं वेक्टर के आकार +1 करने के लिए, अगर आकार 0. से ऊपर है तो यह मैं क्या किया है की कोशिश करेंगे खंड, मुझे त्रुटि assignment of read-only data-member 'Example::m_value' मिलती है जो सभी मुझे समझ में आता है, मुझे उन त्रुटियों को प्राप्त करना है, लेकिन मैं उनके आसपास कैसे जा सकता हूं?

संपादित करें: केवल m_value संपादित करने का एकमात्र तरीका ऑब्जेक्ट के अंदर है (क्योंकि m_value निजी है)। केवल गेटर होने से मुझे m_value को कन्स्ट्रक्टर में सेट किए गए किसी भी चीज़ से अलग करने से सीमित कर दिया जाएगा। क्या मुझे सदस्य चर के रूप में निरंतर int होने से कुछ भी लाभ होता है?

+1

': m_value (! MyVec.empty()? MyVec.size() + 1: -1)'? – hmjd

+0

इसे 'const' क्यों होना चाहिए? – Nim

+0

आपके अपडेट के संबंध में - नहीं, कोई लाभ नहीं जो मैं देख सकता हूं ... – Nim

उत्तर

22

आपको आवश्यक परिणाम की गणना करने के लिए एक स्थिर सदस्य फ़ंक्शन का उपयोग करें और प्रारंभिक सूची में उस फ़ंक्शन को कॉल करें। इस तरह:

// Example.h 
class Example { 
    public: 
     Example(const int value); 
     Example::Example(std::vector<Example*> myVec); 

     const int getValue() const; 
    private: 
     const int m_value; 

     static int compute_m_value(::std::vector<Example*> &myVec); 
}; 

// Example.cpp 
#include "Example.h" 

Example::Example(const int value) 
: m_value(value) 
{ 
} 

Example::Example(std::vector<Example*> myVec) 
: m_value(compute_m_value(myVec) 
{ 
} 

const int Example::getValue() const 
{ 
    return m_value; 
} 

int Example::compute_m_value(::std::vector<Example*> &myVec) 
{ 
    if (myVec.size()) { 
     return myVec.size() + 1; 
    } 
    else { 
     return -1; 
    } 
} 

इस विशेष मामले में, समारोह आप बस निर्माता में त्रिगुट ऑपरेटर (उर्फ : m_value(myVec.size() > 0 ? myVec.size() + 1 : -1) का उपयोग कर सकते सीधे प्रारंभ में मूल्य की गणना करने तो बहुत सरल है। यह एक उदाहरण की तरह दिखता था, इसलिए मैंने आपको समस्या को हल करने का एक बहुत ही सामान्य तरीका दिया, भले ही आपके द्वारा आवश्यक उत्तर की गणना करने की विधि बहुत जटिल हो।

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

+1

+1, और स्पष्ट स्पष्टीकरण। – undu

5

सबसे पहले, परिवर्तनीय श्रेणी परिभाषा में परिभाषित किया गया है, कन्स्ट्रक्टर में नहीं। यह कन्स्ट्रक्टर में प्रारंभ किया गया है।

Example::Example(std::vector<Example*> myVec) 
    : m_value(myVec.size() ? myVec.size() + 1 : -1) { 
} 
+1

यह इस उदाहरण के बहुत संकीर्ण मामले में समस्या हल करता है। इसके बारे में क्या है कि प्रारंभकर्ता की गणना करने के लिए कोड एक अभिव्यक्ति में फिट करने के लिए प्रबंधन से अधिक जटिल है? – Omnifarious

+1

@ ओमनिफरीस - Omnifarious द्वारा दिए गए उत्तर को देखें। –

+0

@ ओम्निफिरियस: फिर आप एक छोटा फ़ंक्शन हेल्पर लिखते हैं जो इसे करता है –

0

आप दो बुनियादी विकल्प हैं: प्रारंभकर्ता सूची से में मूल्य की दुकान:

दूसरा, तरीका है कि ऐसा करने के लिए सिर्फ तुम क्या अपने निर्माता वर्तमान में है की तरह है।

Example::Example(const std::vector<Example*> &myVec) 
    : m_value(myVec.size() ? myVec.size() + 1 : -1) 
{} 

अधिक जटिल चीज़ों के लिए, आप एक सदस्य कार्य करने के लिए गणना प्रतिनिधि कर सकते हैं: एक सशर्त ऑपरेटर, जिसमें आपकी जैसी सरल की स्थिति के लिए ठीक है का उपयोग करें। सावधान रहें कि इसमें वर्चुअल सदस्य फ़ंक्शंस को कॉल न करें, क्योंकि इसे निर्माण के दौरान बुलाया जाएगा।यह static बनाने के लिए सबसे सुरक्षित है:

class Example 
{ 
    Example(const std::vector<Example*> &myVec) 
    : m_value(initialValue(myVec)) 
    {} 

    static int initialValue(const std::vector<Example*> &myVec) 
    { 
    if (myVec.size()) { 
     return myVec.size() + 1; 
    } else { 
     return -1; 
    } 
    } 
}; 

बाहर के वर्ग परिभाषा के साथ बाद में काम करता है और साथ ही जाहिर है,। मैंने अंतरिक्ष & टाइपिंग को संरक्षित करने के लिए उन्हें कक्षा में रखा है।

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