0

我正在学习 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;
}

还有更多,但我认为这就是与问题有关的全部

4

3 回答 3

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';
}

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

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

现在您必须传递要排序的数据。您可以使用 std::bind 或更好的 C++11 lambda 来执行此操作。然后,正如 Yakk 的回答中所指出的,我们可以模板化计时器函数,以便它本机接受 std::functions、lambdas、仿函数(具有 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 lambda):

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()});

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

als.timeOperation( std::bind( &arrayListStruction::insertionSort, als ) );
于 2013-02-04T19:22:21.500 回答
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;
}

请参阅此演示

于 2013-02-04T19:27:21.850 回答
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没有开销的情况下在其中调用。

于 2013-02-04T19:30:21.340 回答