2009-05-28 75 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()`(``将其标记为代码)。 – 2009-05-28 19:59:58

+0

如果你正在返回号码,为什么它应该是私人的? – 2009-05-28 23:02:05

+0

我扩展了这个例子,以显示只有AskBase :: ask_user()返回仅由ask_runUI()使用的s_EOF。 – 2009-06-16 05:22:47

回答

22

如果你想让一个模板函数成为朋友,你必须在类声明中这么说。将声明朋友函数的行更改为:

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

现在,如果您的类本身是一个模板,事情会变得更加复杂。模板的朋友并不是微不足道的做得正确。为此,我会告诉你什么C++ FAQ Lite就这个问题说。

-2

最简单的可能是更换static int const成员枚举,而不是乱用friend S:


class AskBase { 
public: 
    enum { Eof = -99, Null = 0, Ok = 1, Backup = -1 }; 
    ... 
}; 
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; 
}