2010-03-09 10 views
6

में चारों ओर घूम रहा है इसलिए मैं can't use initializers in my class constructor सरणी का उपयोग करने के कारण, इसलिए मैंने init() विधि का उपयोग करने का निर्णय लिया। अब मुझे एक अलग समस्या है। मैं इस तरह एक वर्ग है:एक इनिट विधि

class EPWM { 
private: 
    volatile EPWM_REGS* const regs; 
public: 
    void init(volatile EPWM_REGS* _regs); 
}; 

जहाँ मैं regs = _regs; आरंभ से init() लागू करने की आवश्यकता है, लेकिन मैं const नहीं की वजह से कर सकते हैं। क्या मेरे init विधि में असाइनमेंट को मजबूर करने का कोई तरीका है? मैं const कीवर्ड रखना चाहता हूं इसलिए मुझे गलती से कहीं और पुन: असाइन नहीं किया गया है।

संपादित करें: के रूप में ज्यादा के रूप में मैं (मेरे कोड यह करने के लिए प्रयोग किया जाता) एक निर्माता + प्रारंभकर्ता उपयोग करने के लिए है, जो इस समस्या का समाधान होगा चाहते हैं, मैं नहीं कर सकता क्योंकि मैं किसी अन्य वर्ग जो EPWM वस्तुओं की एक सरणी है है, और मैं उन वस्तुओं को प्रारंभ नहीं कर सकता क्योंकि सी ++ सरणी सदस्यों के लिए प्रारंभकर्ताओं का समर्थन नहीं करता है। (फिर से, the other question I asked a little while ago on this subject. देखें)

प्रसंग के लिए EPWM का उपयोग कर कुछ इस तरह है:

class PwmGroup { 
private: 
    EPWM *epwm; 

    void init(EPWM *_epwm) { epwm = _epwm; } 
}; 

/* ... */ 
// main code: 

EPWM epwm[3]; 
PwmGroup pwmGroup; 

{ 
    // EPwm1Regs, EPwm2Regs, EPwm3Regs are structs 
    // defined by TI's include files for this processor 
    epwm[0].init(&EPwm1Regs); 
    epwm[1].init(&EPwm2Regs); 
    epwm[2].init(&EPwm3Regs); 
    pwmGroup.init(epwm); 
} 
+0

स्थिरांक 'ctor में सदस्य regs' क्यों init नहीं? क्या यह प्रारंभिकरण के लिए किसी अन्य सरणी पर निर्भर करता है? – dirkgently

+0

मेरे पास एक और कक्षा है जिसमें ईपीडब्ल्यूएम ऑब्जेक्ट्स की एक सरणी है जिसे मैं कन्स्ट्रक्टर में प्रारंभ नहीं कर सकता क्योंकि सी ++ ऐसी चीज की अनुमति नहीं देता है। –

+0

मुझे आपकी समस्या है। हमेशा मुझे डिजाइन के बारे में दो बार सोचने लगता है। – dirkgently

उत्तर

4

आप const_cast और संकेत दिए गए विचार कर सकते हैं, लेकिन यह कुछ सबसे अच्छा शायद ही कभी इस्तेमाल बहुत है। कुछ की तरह ...

EPWM_REGS** regsPP = const_cast<EPWM_REGS**>(&regs); 
*regsPP = _regs; 
+0

यह उन मामलों में से एक की तरह लगता है। कैसे "* (const_cast (और regs)) = _regs;" ? –

+0

(या "* (const_cast (और regs)) = _regs;" मेरे मामले में, जो सही ढंग से संकलित लगता है।) –

+3

यह उन मामलों में से एक है जहां const_cast को काम करने की गारंटी नहीं है, क्योंकि जिस चीज को आप कास्टिंग कर रहे हैं वह वास्तव में स्थिर है (उदाहरण के लिए एक विधि पैरामीटर में जोड़ा गया है)। –

0

इस तरह एक निर्माता का उपयोग करें:

EPWM::EPWM(volatile EPWM_REGS* _regs) 
    : regs(_regs) 
{} 

तब बस अपने init में कोई पैरामीटर है:

void EPWM::init() 
{ 
    // do something with this->regs here... 
} 

दूसरे शब्दों में, आप में सब कुछ आरंभ कर सकते हैं वर्ग कन्स्ट्रक्टर - बस सदस्य सरणी नहीं।

+2

मैं नहीं कर सकता। मेरे संपादन को बारीकी से पढ़ें। –

1

निम्नलिखित के बारे में कैसे?

struct EPWM_array { 
    EPWM_array() { /* initialize array */ } 
    const EPWM *begin() const; 
    const EPWM *end() const; 

    EPWM array[ 10 ]; 
}; 

struct EPWMWrapper { 
    volatile EPWM_REGS* const regs; 
    EPWMWrapper(EPWM_array const& a) : regs(a.begin()) {} 
}; 
+0

EPWM_array आवेदन कोड है? चलो विभाजन के बारे में बात करते हैं: मैं ईपीडब्लूएम और पीडब्ल्यूएम समूह को लाइब्रेरी कोड के रूप में परिभाषित करना चाहता हूं जिसे मैं काम पर ला सकता हूं और इसे अपरिवर्तित रख सकता हूं। मेरे आवेदन कोड में, मैं पीएमएम ग्रुप/ईपीडब्लूएम [3] के उदाहरणों को कॉन्फ़िगर करना चाहता हूं (EPWM_REGS *) जो कि एक एप्लिकेशन से दूसरे में बदल सकता है, इस पर निर्भर करता है कि मेरा एप्लिकेशन इस विशेष भाग के परिधीय उपयोग कैसे करता है। अगर मैं आपका उदाहरण समझता हूं, तो EPWM_array() अपने कन्स्ट्रक्टर में प्रारंभिकरण के विवरण को संभालता है। दुर्भाग्यवश जिस तरह से मैं चाहता हूं उसे विभाजित करने के लिए, मुझे लगता है कि मुझे आभासी उप-वर्गों का उपयोग करना होगा: -/ –

+0

हम्म .... या शायद नहीं। क्या EPWM_array को फिर से लिखने का कोई तरीका है, इसलिए मैं अपने सरणी सदस्यों को निर्माण समय पर प्रारंभ नहीं करता, बल्कि बाद के बिंदु पर? यह निराशाजनक है .... –

+0

@ जेसन एस: निश्चित क्यों नहीं? सुनिश्चित करें कि आप 'EPWM_array' तत्काल होने से पहले 'EPWMWrapper' को तुरंत चालू न करें। मुझे यकीन नहीं है कि आपको वर्चुअल सबक्लास की आवश्यकता है, लेकिन उप-वर्गीकरण की आवश्यकता हो सकती है। विरासत का उपयोग करने में कोई समस्या है? जिस तरह से मैं इसे देखता हूं, आपका 'ईपीडब्ल्यूएमप्रैपर' डिज़ाइन वास्तव में एक इंटरफ़ेस की ओर तैयार किया जाना चाहिए, यदि आप चाहते हैं कि आपके उपयोगकर्ता 'EPWM_array' उदाहरण प्रदान करें। – dirkgently

1

क्या यह कुछ मदद चाहिए? आप अभी भी जानबूझकर स्थिरता का उल्लंघन कर सकते हैं लेकिन यह सामान्य लोगों को मूर्खतापूर्ण गलतियों से रोकता है (मैंने इसे संकलित नहीं किया है)।

class EPWM { 
private: 
    volatile EPWM_REGS* regs_for_init_never_use; 
    volatile EPWM_REGS* const& regs; 
public: 
    EPWM() : regs(regs_for_init_never_use) 
    void init(volatile EPWM_REGS* _regs); 
}; 
+0

दिलचस्प .... मुझे यह पता लगाने के लिए कुछ बार देखना पड़ा कि आप अन्य पॉइंटर के लिए उपनाम संदर्भ के रूप में कॉन्स्ट संदर्भ प्रारंभ कर रहे हैं। –

1

डेविल्स एडवोकेट बजाना: स्पष्ट प्रलेखन के इरादे से अलग है, क्योंकि यह एक निजी विशेषता है, तो आप पूरी तरह से const कीवर्ड का उपयोग नहीं कर सकता है और init विधि से अलग इसे संशोधित नहीं।

आपका const_cast वास्तव में यहाँ व्यवहार अपरिभाषित हो सकता है, और मैं निश्चित रूप से उन अंधेरे कोनों, जो कुछ भी समाधान में चलाने के लिए नहीं पसंद करते हैं।

class EPWM { 
private: 
    volatile EPWM_REGS* regs; // normally const, but need to be inited :/ 
public: 
    void init(volatile EPWM_REGS* _regs); 
}; 

हालांकि, आपके सवाल फिर से मिलना: जबकि एक raw सरणी जा निर्माण नहीं कर सकती है आप एक सरणी वर्ग कि हो सकता है लिख सकते हैं।

namespace detail 
{ 
    template <class T, size_t N, size_t index> 
    struct At 
    { 
    static T& Do(Array<T,N>& array) 
    { 
     return At<T,N-1,index-1>::Do(array.tail()); 
    } 
    }; 

    template <class T, size_t N> 
    struct At<T,N,0> 
    { 
    static T& Do(Array<T,N>& array) { return array[0]; } 
    }; 

    template <class T, size_t index> 
    struct At<T,0,index> {}; 

    template <class T> 
    struct At<T,0,0> {}; 
} // namespace detail 


template <class T, size_t N> 
class array 
{ 
public: 
    typedef T value_type; 
    static const size_t Length = N; 

    array(): mHead(), mTail() {} 
    array(const array& rhs): mHead(rhs.mHead), mTail(rhs.mTail) {} 

    // Don't know whether it will be optimized or not 
    // Not sure I can use pointer arithmetic either :p 
    T& operator[](size_t index) { return index == 0 ? mHead : mTail[index-1]; } 

    // Compile time access 
    template <size_t index> 
    T& at() { return detail::At< T, N, index >::Do(*this); } 

private: 
    T mHead; 
    array<T, N-1> mTail; 
}; // class array<T,N> 

template <class T> 
class array<T,1> 
{ 
public: 
    typedef T value_type; 
    static const size_t Length = 1; 

    array(): mHead() {} 
    array(const array& rhs): mHead(rhs.mHead) {} 

    T& operator[](size_t index) { return mHead; } // or error handling ;) 

private: 
    T mHead; 
}; // class array<T,1> 

template <class T> class array<T,0> {}; // int[0] does not work (stack) so... 

ठीक है ... शायद के रूप में एक वास्तविक सरणी के रूप में कुशल नहीं है ... तुम हमेशा पीढ़ी Preprocessor हालांकि चालू कर सकते हैं:

template <class T> 
class Array4 
{ 
public: 
    Array4(): m0(), m1(), m2(), m3() {} 
    Array4(const Array4& rhs): m0(rhs.m0), m1(rhs.m1), m2(rhs.m2), m3(rhs.m3) {} 

    T& operator[](size_t index) { return *(&m0 + index); } 

private: 
    T m0; 
    T m1; 
    T m2; 
    T m3; 
}; // class Array4<T> 
संबंधित मुद्दे