1

考虑 Zaita 在cplusplus.com上发布的有用代码,特别是安全获取数字的部分,在我的情况下修改为函数:

int get_number()
{
   /**
    * cplusplus.com/forum/articles/6046
    * gets number from input stream
    **/

   string input = "";
   int number = 0;

   while (true)
   {
      getline(cin, input);
      stringstream checks(input);
      if (checks >> number)
         return number;
      cout << "Please enter a valid number\n";
   }
}

现在,我的问题是:我可以删除intget_number() 的函数定义的第一行,并在我的代码顶部用我可能想要返回的所有类型声明它,例如做一些这样的声明:

double get_number();
int get_number();
long get_number();
unsigned short get_number();
...
...

并以某种方式让它根据我想存储函数返回的变量来做不同的返回?目前我只是在将名称更改为get_someType

我希望我可以用这种语法做类似声明:

int get_number(int);
double get_double(double);
...
...

我的愿望是做类似的事情:

int x;
x = get_number(int);

我相信这不会起作用!因为用没有名字的参数来定义函数的源代码是不可能的......

4

5 回答 5

6

首先,您发现的 get_number 实现写得很糟糕:您认为当您在输入中获得 EOF 时会发生什么?它会尽可能快地打印“请输入一个有效的数字\n”,直到你杀死程序......

其次,您不能重载返回类型——这意味着您不能拥有仅在返回类型上有所不同的函数。

最后,C++ 有模板可以做我认为你想要的......

template <typename T>
bool get(T& x)
{
    std::string input;
    if (!getline(std::cin, input))
        return false;
    stringstream checks(input);
    if (checks >> x)
        return true;
    cout << "Please enter a valid value\n";
}

然后你可以使用if (get(my_int)) ...orif (get(my_double))等​​等..

由于输入不能保证成功,你真的应该提供一个布尔返回类型(如图所示),或者一旦明确输入不能成功就抛出异常。

于 2013-02-01T06:01:27.617 回答
3

您正在寻找功能templates

这段代码有问题(请不要使用 cplusplus.com 作为参考),因为它不检查std::cin是否收到了来自的输入。

一个模板化的例子看起来像这样(未经测试):

#include <string>
#include <sstream>
#include <iostream>
#include <stdexcept>

template <typename T>
T get_number()
{
    std::string input = "";
    T number; // Don't initialise to zero
    bool done = false;

    while (!done)
    {
        if (std::getline(std::cin, input)) // check for success
        {
            std::istringstream checks(input);
            if (checks >> number)
            {
                done = true;
            }
            else
            {
                std::cout << "Please enter a valid number\n";
            }
        }
        else
        {
            throw std::runtime_error("No input was received\n");
        }
    }
    return number;
}

int main()
{
    try
    {
        int i = get_number<int>();
        float f = get_number<float>();
        double d = get_number<double>();
        char b = get_number<char>();
    }
    catch (const std::runtime_error& e)
    {
        std::cerr << e.what() << std::endl;
    }
}

要将我的评论合并到这个答案中......在类模板或函数模板中,typename可以用作class声明模板类型的替代方法。我更喜欢typename因为我们处理的是 POD 类型而不是classes。

于 2013-02-01T05:59:15.513 回答
2

这可以通过模板来完成。

在这里你可以找到一些初学者的模板教程(从58开始..) http://thenewboston.org/list.php?cat=16

于 2013-02-01T06:02:25.313 回答
1

您可以使用模板,但据我所知,您的函数也必须具有该模板类型的参数,如:

template <class T>
T get_number(T arg)
{
   /**
    * cplusplus.com/forum/articles/6046
    * gets number from input stream
    **/

   string input = "";
   T number = 0;

   while (true)
   {
      getline(cin, input);
      stringstream checks(input);
      if (checks >> number)
         return number;
      cout << "Please enter a valid number\n";
   }
}

模板 ( T) 的类型在编译时根据传递给函数的参数类型进行解析。

于 2013-02-01T05:59:54.420 回答
1
template<class T>
T get_number()
{
   /**
    * cplusplus.com/forum/articles/6046
    * gets number from input stream
    **/

   string input = "";
   T genericobj;

   while (true)
   {
      getline(cin, input);
      stringstream checks(input);
      if (checks >> genericobj)
         return genericobj;
      cout << "Please enter a valid input\n" ;
   }
}
于 2013-02-01T06:03:00.287 回答