2014-09-12 15 views
6

निम्नलिखित टेम्पलेट वर्ग पर विचार के साथ टेम्पलेट:सी ++ 'स्थिरांक'

template <typename T> class Function { 
public: 
    virtual float eval(const T &x, const T &y) = 0; 
}; 

'eval' समारोह के बाद से दो आदानों 'एक्स' का मूल्य संशोधित नहीं करना चाहिए और 'y', मैं उन्हें 'के रूप में डाल दिया स्थिरांक '। तो मैं निम्नलिखित वर्ग समारोह

class Foo1 : public Function <float*> { 
public: 
    Foo1() : Function <float*>() {} 
    virtual float eval(const float* &x, const float* &y) { ... } 
}; 

से ली गई जब मैं जी के साथ संकलन बनाने ++, मैं निम्नलिखित चेतावनी मिलती है:

hidden overloaded virtual function 'Function<float *>::eval' declared here: type mismatch at 1st parameter 
     ('float *const &' vs 'const float *&') 
     virtual float eval(const T &x, const T &y) = 0; 

और मैं वर्ग Foo1 का दृष्टांत नहीं कर सकते। कंपाइलर का कहना है कि समारोह 'eval' लागू नहीं किया गया है। संकलक को खुश करने के लिए, व्युत्पन्न वर्ग के रूप में होना चाहिए इस प्रकार है:

class Foo2 : public Function <float*> { 
public: 
    Foo2() : Function <float*>() {} 
    virtual float eval(float* const &x, float* const &y) { ... } 
}; 

foo2 :: eval समारोह के बजाय 'स्थिरांक नाव *' के प्रकार 'नाव * स्थिरांक' दो पैरामीटर उपयोग करता है। दूसरे शब्दों में, Foo2 :: eval arrays 'x' और 'y' की सामग्री को संशोधित कर सकता है। यह वह नहीं है जिसकी मुझे चाहत है।

मैं इस प्रकार टेम्पलेट वर्ग 'समारोह' को बदलने की कोशिश की है:

virtual float eval(T const &x, T const &y) = 0; 

लेकिन वर्ग Foo1 अभी भी काम नहीं करता है, वर्ग foo2 पिछले मामले में के रूप में काम करता है।

  1. तो ऐसा लगता है कि या तो 'स्थिरांक टी & एक्स' या टेम्पलेट कक्षा में 'टी स्थिरांक & एक्स' व्युत्पन्न वर्ग में निकलता है 'नाव * स्थिरांक & एक्स'। क्या ये सही है?
  2. यदि मैं व्युत्पन्न कक्षा में 'कॉन्स्ट फ्लोट * & x' (या 'कॉन्स्ट फ्लोट * एक्स') चाहता हूं, तो मेरा टेम्पलेट क्लास फ़ंक्शन क्या होना चाहिए?

धन्यवाद।

उत्तर

1

ऐसा लगता है कि या तो const T &x या T const &x टेम्पलेट कक्षा में निकलता है व्युत्पन्न वर्ग में float* const &x। क्या ये सही है?

हाँ, यह सही है। इसके बारे में सोचने का तरीका यह है कि T हमेशा const है; आपके मामले में T एक सूचक होने के लिए होता है।

अगर मैं const float* &x (या const float* x) व्युत्पन्न वर्ग में चाहते हैं, क्या मेरे टेम्पलेट वर्ग समारोह होना चाहिए?

लगता है जैसे यह class Foo2 : public Function <const float*> होना चाहिए।

template <typename T> class Function<T*> { 
    public: 
     virtual float eval(const T* x, const T* y) = 0; 
}; 

वैकल्पिक रूप से, आप Function<const float*> से Foo2 प्राप्त कर सकते हैं:

0

एक तरह से बाहर आंशिक रूप से सूचक प्रकार के लिए Function विशेषज्ञ के रूप में eval के लिए अलग हस्ताक्षर का प्रयोग है।

8

आपके द्वारा देखे जाने वाले व्यवहार 100% सही हैं जहां तक ​​मानक का संबंध है। यह "निरंतर सूचक" बनाम "स्थिर करने के लिए सूचक" का क्लासिक उदाहरण है।

आपका प्राथमिक टेम्पलेट वाणी यह ​​एक ", जिसके माध्यम से यह T वस्तु संशोधित नहीं कर सकते T के संदर्भ में करने के लिए भेजा जा रहा है" लेता है (सिंटेक्स const T & है, T const & के समकक्ष)।

फिर, आप टेम्पलेट को float* के साथ तत्काल चालू करें, यानी "float पर सूचक।" इस प्रकार से टेम्पलेट पैरामीटर प्रतिस्थापन के बाद फ़ंक्शन पैरामीटर प्रकार वास्तव में "float * का संदर्भ है जिसके माध्यम से यह float * को संशोधित नहीं कर सकता है।" धुंधला करने का कोई तरीका नहीं है "float को संशोधित नहीं कर सकता है, जिसमें float * सीधे बिंदुओं पर संदर्भित किया जा रहा है"।

मुझे दो विकल्प दिखाई देते हैं। एक, यदि उपयोग इस तरह का Function में T का ही इस्तेमाल होता है, बस const float * टेम्पलेट तर्क के रूप में, का उपयोग के बाद से है कि T आप वास्तव में चाहते हैं:

class Foo1 : public Function <const float*> { 
public: 
    Foo1() : Function <const float*>() {} 
    virtual float eval(const float* const &x, const float* const &y) { ... } 
    // notice two `const` keywords above: one for the pointed object, one for the reference 
}; 

है कि आप के लिए एक विकल्प (यानी अगर नहीं है आपको float *Function और const float* के अंदर कहीं और चाहिए), आपको कुछ प्रकार के लक्षणों का उपयोग करना होगा और eval के पैरामीटर को संशोधित करना होगा। कुछ ऐसा:

template <class T> 
struct unmodifiable { 
    typedef const T &type; 
}; 

template <class T> 
struct unmodifiable<T*> { 
    typedef const T* const &type; // if you want to keep the reference 
    // or just: 
    // typedef const T *type; // if you don't want to bother with the reference for pointer types 
}; 

template <typename T> class Function { 
public: 
    virtual float eval(typename unmodifiable<T>::type x, typename unmodifiable<T>::type y) = 0; 
}; 

class Foo1 : public Function <float*> { 
public: 
    Foo1() : Function <float*>() {} 
    virtual float eval(unmodifiable<float*>::type x, unmodifiable<float*>::type y) { ... } 
    // or just spell it out exactly, based on the variant of `unmodifiable` you've chosen, e.g.: 
    // virtual float eval (const float *x, const float *y) { ... } 
}; 
संबंधित मुद्दे