2009-05-28 18 views
5

şablon işlevi s_EOF yapmadan ask_runUI() şablon işlevine izin vermek için aşağıdaki kodu nasıl değiştirir?Şablon işlevinin arkadaş (benzeri) erişimine sahip olmasına nasıl izin verilir?

#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

Bir dahaki sefere, lütfen 'int ask_runUI()' işlevini kullanın ('' kodu yaz). –

+0

Numarayı iade ediyorsanız, neden özel olmalı? –

+0

Örnekte, yalnızca AskBase :: ask_user() öğesinin yalnızca ask_runUI() tarafından kullanılan s_EOF değerini döndürdüğünü göstermek için genişlettim. –

cevap

22

Bir şablonun işlevinin arkadaş olmasını istiyorsanız, sınıf bildiriminde bunu söylemelisiniz. sınıf bir şablon kendisi ise

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

Şimdi, işler çok daha karmaşık alıyorum: Bu Arkadaş işlevini bildirir satırı değiştirin. Şablon arkadaşlar doğru bir şekilde yapmak için önemsiz değildir. Bunun için konuyla ilgili C++ FAQ Lite'un ne söylediğine bakacağım. Muhtemelen friend s ile static int const sayma yöntemiyle üyeleri ve karışıklık yerine edilmektedir

-2

basit: Bu benim için çalıştı


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

-1. Bunun bir şeyi nasıl değiştirdiğini görmüyorum - kamuoyuna açıkladığınız enum, sadece statik inisiyatif üyelerini kamuya açmaya eşdeğer bir şekilde. Kaçırdığım bazı ayrıntılar varsa lütfen tekrar söyleyeyim. –

+0

Ayrıntı, derleyicinin statik üye değişkenleri için alan ayırması gerekmediğidir. Avantajı, bu basit. –

+0

Eh, biraz araştırma yaptım ve düşündüğümden daha garip. Birincisi, sınıf tanımı * içindeki statik const int üyelerini * isim-alanı düzeyinde tanımlamaksızın (yani, isim alanı düzeyinde "statict const int AskBase :: s_Eof; hiç ayrılmak. AMA, derleyici sadece s_Eof'a bir değer olarak başvurmanıza izin verir (örneğin, bir non-const'a bağlantı, bağlantı zamanında başarısız olur!) Bkz .: http://stackoverflow.com/questions/272900/c-undefined -Sonra-sınıf-sınıf üyesi, özellikle Richard Corden'ın cevabı. –

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

Bu bir şablon yöntemini arkadaşlık için klasik anti-desen var. Temelde herkes kendi halkının sor_runUI() –

+3

kendi versiyonunu yazabildiği gibi herkese açık hale getirmekle aynıdır. Ancak, onlar bunu yaparken ne yaptıklarını fark etmeden kazara yaparlar mı? Özellikle, eğer ask_UI sınıfla aynı isim alanındaysa, bir sınıfın ara yüzünün içinde dolaşırlarsa mutlaka kapsüllemeyi kırdıklarını biliyorlar mı? –

İlgili konular