2009-05-28 3 views
5

कैसे एक टेम्पलेट समारोह ask_runUI()s_EOF को सार्वजनिक किए बिना s_EOF उपयोग करने की अनुमति के लिए निम्न कोड को संशोधित करता है?टेम्पलेट फ़ंक्शन को मित्र (जैसे) पहुंच रखने की अनुमति कैसे दें?

#include <string> 
#include <iostream> 
#include <sstream> 
#include <vector> 
class AskBase { 
protected: 
    std::string m_prompt; 
    std::string m_answer; 
    virtual bool validate(std::string a_response) = 0; 
public: 
    AskBase(std::string a_prompt):m_prompt(a_prompt){} 
    std::string prompt(){return m_prompt;} 
    std::string answer(){return m_answer;} 
    static int const s_EOF = -99; 
    static int const s_BACKUP = -1; 
    static int const s_OK = 1; 
    int ask_user(); 
}; 
template<typename T> class Ask : public AskBase{ 
public: 
    Ask(std::string a_prompt):AskBase(a_prompt){} 
    bool validate(std::string a_response); 
}; 
template<> bool Ask<std::string>::validate(std::string a_response){return true;} 
template<> bool Ask<int>::validate(std::string a_response){int intAnswer; 
    return (std::stringstream(a_response) >> intAnswer);} 
int AskBase::ask_user(){ 
    for(;;){ 
     std::cout << "Enter " << m_prompt; 
     std::string response; 
     getline(std::cin, response); 
     if (std::cin.eof()) 
      return s_EOF; 
     else if (response == "^") 
      return s_BACKUP; 
     else if (validate(response)){ 
      m_answer = response; 
      return s_OK; 
     } 
    } 
    return s_EOF; 
} 
template<typename T> int ask_runUI(T& a_ui){ 
    int status = AskBase::s_OK; 
    for (typename T::iterator ii=a_ui.begin(); 
      status!=AskBase::s_EOF && ii!=a_ui.end(); 
      ii+=((status==AskBase::s_BACKUP)?((ii==a_ui.begin())?0:-1):1) 
     status = (*ii)->ask_user(); 
    return (status == AskBase::s_OK); 
} 
int main(){ 
    std::vector<AskBase*> ui; 
    ui.push_back(new Ask<std::string>("your name: ")); 
    ui.push_back(new Ask<int>("your age: ")); 
    if (ask_runUI(ui)) 
     for (std::vector<AskBase*>::iterator ii=ui.begin(); ii!=ui.end(); ++ii) 
      std::cout << (*ii)->prompt() << (*ii)->answer() << std::endl; 
    else 
     std::cout << "\nEOF\n"; 
} 
+0

अगली बार, कृपया 'int ask_runUI() '(' 'इसे कोड के रूप में चिह्नित करें) का उपयोग करें। –

+0

यदि आप नंबर लौट रहे हैं, तो यह निजी क्यों होना चाहिए? –

+0

मैंने यह दिखाने के लिए उदाहरण का विस्तार किया कि केवल AskBase :: ask_user() s_EOF लौटाता है जिसका उपयोग केवल ask_runUI() द्वारा किया जाता है। –

उत्तर

22

यदि आप टेम्पलेट फ़ंक्शन को मित्र बनना चाहते हैं, तो आपको कक्षा घोषणा में ऐसा कहना होगा।

template <typename T> 
friend int ask_runUI(T& a_ui); 

अब, अगर अपने वर्ग अपने आप में एक टेम्पलेट है, चीजों को एक बहुत अधिक जटिल हो: लाइन यह करने के लिए दोस्त समारोह घोषणा करता है कि परिवर्तित करें। टेम्पलेट दोस्तों सही ढंग से करने के लिए तुच्छ नहीं हैं। इसके लिए, मैं आपको इस विषय पर C++ FAQ Lite पर बताऊंगा।

-2

सरल शायद friend रों साथ गणन साथ static int const सदस्यों और नहीं गंदगी को बदलने के लिए है:


class AskBase { 
public: 
    enum { Eof = -99, Null = 0, Ok = 1, Backup = -1 }; 
    ... 
}; 
+0

-1। मैं नहीं देखता कि यह कैसे कुछ बदलता है - आपका enum, जिसे आपने सार्वजनिक घोषित किया है, हर भौतिक रूप से स्थिर स्थिरांक सदस्यों को सार्वजनिक बनाने के बराबर है। अगर कुछ भेद है तो मुझे याद आया है, कृपया कहें और मैं पुनर्विचार करूंगा। –

+0

भेद यह है कि कंपाइलर को स्थिर सदस्य चर के लिए स्थान आवंटित करने की आवश्यकता नहीं है। लाभ यह है कि यह सरल है। –

+0

ठीक है, मैंने कुछ शोध किया और यह मैंने सोचा की तुलना में कमजोर है। एक के लिए, यदि आप बस घोषित करने और वर्ग परिभाषा के अंदर स्थिर स्थिरांक पूर्णांक सदस्यों आरंभ * बिना * नाम स्थान स्तर पर उन्हें परिभाषित करने (लेखन के बिना यानी "statict स्थिरांक पूर्णांक AskBase :: s_Eof," नाम स्थान स्तर पर आदि) तो कोई स्थान खाली नहीं होगा कभी आवंटित किया जाएगा। http://stackoverflow.com/questions/272900/c-undefined: लेकिन, संकलक केवल आप एक rvalue (जैसे एक गैर स्थिरांक रेफरी के लिए बाध्य लिंक समय !! पर विफल हो जाएगा) के रूप में s_Eof का उल्लेख यहाँ देखें करने की अनुमति देगा -फ्रेंस-टू-स्टेटिक-क्लास-सदस्य, विशेष रूप से रिचर्ड कॉर्डन का जवाब। –

2

यह मेरे लिए काम किया!

class AskBase { 
public: 
    AskBase(){} 
    template<typename T> 
    friend int ask_runUI(T& a_ui); 
private: 
    static int const s_EOF = -99; 
    static int const s_BACKUP = -1; 
    static int const s_NULL = 0; 
    static int const s_OK = 1; 
}; 
//int ask_runUI() 
template<typename T> 
int ask_runUI(T& a_ui) 
{ 
    return AskBase::s_NULL; 
} 
+1

यह टेम्पलेट विधि को फ्रेन्ड करने के लिए क्लासिक एंटी-पैटर्न है। यह मूल रूप से सभी सदस्यों को सार्वजनिक किसी को भी अब ask_runUI() –

+3

वे कर सकते हैं के अपने स्वयं के संस्करण के रूप में लिख सकते हैं बनाने के रूप में ही है, लेकिन वे एहसास है कि वे क्या कर रहे है बिना दुर्घटना से ऐसा करने के लिए होगा? विशेष रूप से यदि ask_UI कक्षा के समान नामस्थान में है, तो यदि वे कक्षा के इंटरफ़ेस के अंदर चारों ओर घूमते हैं तो निश्चित रूप से वे जानते हैं कि वे encapsulation तोड़ रहे हैं? –

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