将方法作为参数传递给另一个方法的可能性

时间:2013-02-04 19:11:28

标签: c++

我正在学习c ++,我想知道我是否可以在另一个方法中将方法作为参数传递?

我想要做的大致概述是这样的:

void insertionSort() {
   //perform sort
}

int timeOfOperation(methodInQuestion) {
    // time 1
    methodInQuestion;
    //time 2
    return time2-time;
}

int main() {
   cout << timeOfOperation(insertionSort());
   return 0;
}

有没有办法做这样的事情?

编辑:

我很感谢回复。我有另一个问题。在我的实际代码中,这一切都发生在一个名为dataStructure的类中,我正在其他地方创建一个实例并调用这些方法。

dataStructure ds();
ds.timeOperation(ds.insertionSort());

当我尝试实施一些已发布的解决方案时,我收到此错误:

IntelliSense: no instance of function template
"dataStructure::timeOperation" matches the argument list argument
types are: (void) object type is: dataStructure

我真的不明白为什么创建实例会影响这一点。谁能解释一下?

=============================================== ==============

编辑2:

我将或多或少地发布这部分的确切代码:

//main.cpp

#include "arrayList.h"
#include "arrayListStructure.h"
#include "Person.h"

using namespace std;

int main() {

    arrayList<Person> *al = new arrayList<Person>(length);
    arrayListStructure als(al);
    //als.fillStructure(data);
    als.timeOperation(als.insertionSort());

return 0;
}


//arrayListStructure.cpp

#include "arrayListStructure.h"
#include <functional>

double arrayListStructure::timeOperation(std::function<void()> operation) {...}
void arrayListStructure::insertionSort() {...}

arrayListStructure::arrayListStructure(arrayList<Person> *al)
{
this -> al = al;
}

还有更多,但我认为这与问题有关

3 个答案:

答案 0 :(得分:2)

是的,比如:

#include <functional>
#include <ctime>
#include <iostream>

void insertionSort() { /*...*/ }

std::clock_t timeOfOperation( std::function<void()> operation ) 
{
    const std::clock_t start = std::clock();
    operation();
    return std::clock() - start;
}

int main() 
{
    std::cout << timeOfOperation(insertionSort) << '\n';
}

由于您可能不需要全局数据(像insertSort这样的无参数函数需要),您可能会执行以下操作:

template<class Container>
void insertionSort( Container& c ) 
{ 
   /*sort the contents of c*/ 
}

现在你必须传递要排序的数据。你可以使用std :: bind或更好的C ++ 11 lambdas来完成。然后,如Yakk的回答所述,我们可以对计时器函数进行模板化,以便本机接受std :: functions,lambdas,functors(带有operator()重载的类)或函数指针:

template<class Operation>
std::clock_t timeOfOperation( Operation&& operation ) 
{/*...*/ }

这是完整的程序:

#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm> // for generate
#include <ctime> // for clock
#include <cstdlib> // for rand

template<class Container>
void insertionSort( Container& c ) 
{ 
   /*sort the contents of c*/ 
}

template<class Operation>
std::clock_t timeOfOperation( Operation&& operation ) // or just timeOfOperation( Operation&& operation )
{
    const std::clock_t start = std::clock();
    operation();
    return std::clock() - start;
}

int main() 
{
    std::vector<int> v( 100 );
    std::generate( v.begin(), v.end(), std::rand );
    auto op = [&]() { insertionSort( v ); };
    std::cout << timeOfOperation( op ) << '\n';
}

将最后两行(使用C ++ 11 lambdas)组合在一起:

std::cout << timeOfOperation( [&]() { insertionSort( v ); } ) << '\n';

但是,当然,在非家庭作业代码中,你应该使用内置的排序功能,而不是自己编写。


关于你的更新:第一行实际上是一个函数定义,而不是类的实例化:

dataStructure ds(); // function, not an instance!
ds.timeOperation(ds.insertionSort()); // insertionSort returns void. 
// Can't convert void to a template param that can be called with the () operator

在C ++中,规则是,如果可以将某些东西解释为函数原型,那么它就是。放下一些便利,你会没事的:

dataStructure ds; // <-- note
ds.timeOperation(ds.insertionSort());

在回答你的评论时,只要它不能被解释为原型,你就是好的。考虑:

struct S {};

struct dataStructure
{
   dataStructure() {}
   dataStructure(int) {}
   dataStructure(S) {}
   void go() {}
};

int main()
{
    dataStructure ds1 = dataStructure();
    dataStructure ds2(10);
    dataStructure ds3( S() ); 
    dataStructure ds4( (S()) ); // Extra parens clarify for the compiler


    ds1.go(); // Ok  
    ds2.go(); // Ok  
    ds3.go(); // Doh! ds3 is a function prototype
    ds4.go(); // Ok  
}

更新您的编辑2:

更改此行:

als.timeOperation(als.insertionSort());

为:

als.timeOperation([&](){als.insertionSort()});

或(不太喜欢,但如果你没有lambda):

als.timeOperation( std::bind( &arrayListStruction::insertionSort, als ) );

答案 1 :(得分:2)

演示如何使用函数指针


演示:

#include <iostream>
using namespace std;

void insertionSort() {
   cout<<"insertion"<<endl;
}

int timeOfOperation(void(*sortFunc)(void)) {
   sortFunc();
   return 1;
}

int main() {
   cout << timeOfOperation(insertionSort);
   return 0;
}

请参阅 this demo

答案 2 :(得分:2)

在计算操作时,您希望尽可能减少开销。

#include <functional>
#include <ctime>
#include <iostream>

void insertionSort() { /*...*/ }

template<typename F>
std::clock_t timeOfOperation( F&& operation ) {
  const std::clock_t start = std::clock();
  // time 1
  operation();
  //time 2
  return std::clock() - start;
}

int main() {
  std::cout << timeOfOperation(insertionSort) << '\n';
}

这是@metal的解决方案,除了模板。通过std::function调用函数的开销很小。在缺点方面,这意味着我们必须将timeOfOperation的实现放入头文件中。

顺便说一句,如果您的编译器不支持C ++ 11,请将签名中的&&删除到timeOfOperation,这是一个不需要的C ++功能。

如果你想用状态计算多行代码,你可以这样做:

void sort( int* buff, size_t count ) { /* ... */ }

int main() {
  enum { size_of_data = 10 };
  int data[size_of_data] = {1,2,3,4,5,6,-1,0};
  std::cout << timeOfOperation([&](){
    sort( &data[0], size_of_data );
  }) << '\n';
}

使用相同的timeOfOperation - 我在那里写的lambda作为模板化仿函数传入,然后在timeOfOperation内调用,旁边没有开销。