【问题标题】:Passing a function as a parameter CPP将函数作为参数传递 CPP
【发布时间】:2013-11-03 23:21:34
【问题描述】:

我试图在我的主程序中调用一个类函数,该函数将一个函数作为其参数,并将该函数应用于私有列表。我收到错误invalid conversion from char to char (*f)(char)。希望我只是不明白如何将函数作为参数传递。以下是我的主 cpp 文件中的函数

char ToUpper(char c)
{
char b='A';
for(char a='a';a<='z';a++)
{
   if(a==c)
  {
     c=b;
     break;
  }
  ++b;
}
return c;
}

void upperList(LineEditor line)
{
char c;
for(int i=0;i<100;i++)   //ensure iterator is at beginning of line
  line.left();           

for(int i=0;i<100;i++)
{
  c=line.at();               //assign character current element pointed to by iterator
  line.apply(ToUpper(c));    //problem: trying to apply ToUpper function to char c
  line.right();              //apply function and increment iterator
}
}

这是apply成员函数

void LineEditor::apply(char (*f)(char c))
{
*it=f(c);
}

另外,如果不是很明显,我尝试使用 cctypes toupper 和 tolower,但它们接受并返回整数。

【问题讨论】:

  • ` 我尝试使用 cctypes toupper 和 tolower,但它们接受并返回整数。` char 可以隐式转换为 int,或者您可以使用 std::toupper/std::tolower .你的ToUpper 版本效率很低。
  • 是啊哈哈,上面的代码似乎只是将隐式转换抛到了窗外。尽管我已经很容易地实现了这些,但使用来自答案的代码,谢谢!

标签: c++ function class arguments


【解决方案1】:

当您调用ToUpper 时,它不会返回函数,而是以大写形式返回(假定的)字符。

这不起作用的另一个原因是你不能在函数指针的签名中创建参数。参数区域仅指定函数采用的类型。这……

char (*f)(char c);
//        ^^^^^^

因此是错误的。

解决方案:

std::functionstd::bind 用于参数:

#include <functional>

line.apply(std::bind(ToUpper, c));

需要将apply的签名改为:

void LineEditor::apply(std::function<char (char)> f);

如果你不能这样做,你可以简单地让apply接受第二个参数作为参数:

void LineEditor::apply(char (*f)(char), char c);

并将其称为apply(ToUpper, c)

【讨论】:

    【解决方案2】:

    表达式ToUpper(c) 调用函数,但是当调用apply 时你不想立即调用那个函数,所以你需要说apply(ToUpper),因为ToUpper 是访问函数本身的方式.

    【讨论】:

      【解决方案3】:

      表达式 ToUpper(c) 的类型是 char。所以调用

      line.apply(ToUpper(c));
      

      表示以char类型的参数调用函数apply。

      你应该将函数定义为

      void LineEditor::apply( char c, char f(char) )
      {
      *it=f(c);
      }
      

      【讨论】:

      • 你没有在apply函数的任何地方定义it
      【解决方案4】:

      您无需重新发明轮子。 ::toupper::tolower 取回int,但它们的有效范围是unsigned char。此外,std::toupperstd::tolower 都采用char

      由于您似乎没有使用std::string,因此我会尽量使其与您的代码保持一致:

      void upperList(LineEditor line)
      {
          char c;
          // you do not have a begin() function??
          for(int i=0;i<100;i++)   //ensure iterator is at beginning of line
              line.left();           
      
          for(int i=0;i<100;i++)
          {
              c=line.at();
              c = std::toupper(c);
              line.at() = c; // assuming this returns a reference
              line.right(); 
          }
      }
      

      如果您将字符串类修改为更像std::string 类,这将变得更加容易:

      std::string line;
      std::transform(line.begin(), line.end(), line.begin(), std::ptr_fun<int, int>(std::toupper));
      

      Example

      【讨论】:

      • 原来的代码只是一个粗略的拼凑哈哈,现在增加了一些更好的功能和效率:) 谢谢你的回复!
      猜你喜欢
      • 2021-04-13
      • 2019-11-09
      • 2023-04-02
      • 2013-01-27
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      相关资源
      最近更新 更多