【问题标题】:Pointer to function member and non-member指向函数成员和非成员的指针
【发布时间】:2012-10-30 19:50:54
【问题描述】:

摘要

我有一个存储优化问题并针对该问题运行求解器的类。 如果求解器失败,我想考虑一个子问题并使用相同的求解器(和类)进行求解。

简介

优化问题本质上是很多(数学)函数。问题函数是在类外定义的,而子问题函数是在类内定义的,所以它们有不同的类型(例如void (*)void (MyClass::*)

起初我以为我可以将成员函数转换为非成员函数指针类型,但我发现我不能。所以我正在寻找其他方法。

示例代码

模拟我的问题的示例代码:

#include <iostream>

using namespace std;

typedef void (*ftype) (int, double);

// Suppose foo is from another file. Can't change the definition
void foo (int n, double x) {
  cout << "foo: " << n*x << endl;
}

class TheClass {
  private:
    double value;
    ftype m_function;
    void print (int n, double x) {
      m_function(size*n, value*x);
        }
  public:
    static int size;
    TheClass () : value(1.2), m_function(0) { size++; }
    void set_function (ftype p) { m_function = p; }
    void call_function() {
      if (m_function) m_function(size, value);
    }
    void call_ok_function() {
      TheClass ok_class;
      ok_class.set_function(foo);
      ok_class.call_function();
    }
    void call_nasty_function() {
      TheClass nasty_class;
//      nasty_class.set_function(print);
//      nasty_class.set_function(&TheClass::print);
      nasty_class.call_function();
    }
};
int TheClass::size = 0;

int main () {
  TheClass one_class;

  one_class.set_function(foo);
  one_class.call_function();
  one_class.call_ok_function();
  one_class.call_nasty_function();
}

如示例所示,成员函数不能是静态的。另外,我无法重新定义原始问题函数来接收对象。

感谢您的帮助。

编辑

我忘了提。我尝试更改为 std::function,但我原来的函数有超过 10 个参数(它是一个 Fortran 子例程)。

解决方案

我按照建议对std::functionstd::bind 进行了更改,但没有重新设计具有更多10 个参数的函数。我决定创建一个中间函数。以下代码说明了我所做的,但变量较少。谢谢大家。

#include <iostream>
#include <boost/tr1/functional.hpp>

using namespace std;

class TheClass;

typedef tr1::function<void(int *, double *, double *, double *)> ftype;

// Suppose foo is from another file. Can't change the definition
void foo (int n, int m, double *A, double *x, double *b) {
    // Performs matrix vector multiplication x = A*b, where
    // A is   m x n
}

void foo_wrapper (int DIM[], double *A, double *x, double *b) {
    foo(DIM[0], DIM[1], A, x, b);
}

class TheClass {
    private:
        ftype m_function;
        void my_function (int DIM[], double *A, double *x, double *b) {
            // Change something before performing MV mult.
            m_function(DIM, A, x, b);
        }
    public:
        void set_function (ftype p) { m_function = p; }
        void call_function() {
            int DIM[2] = {2,2};
            if (m_function) m_function(DIM, 0, 0, 0);
        }
        void call_nasty_function() {
            TheClass nasty_class;
            ftype f = tr1::bind(&TheClass::my_function, this, _1, _2, _3, _4);
            nasty_class.set_function(f);
            nasty_class.call_function();
        }
};

int main () {
    TheClass one_class;

    one_class.set_function(foo_wrapper);
    one_class.call_function();
    one_class.call_nasty_function();
}

PS。使用

创建一个包含 10 多个变量的 std::function 似乎是可能的(已编译,但我没有测试)
#define BOOST_FUNCTION_NUM_ARGS 15
#include <boost/function/detail/maybe_include.hpp>
#undef BOOST_FUNCTION_NUM_ARGS

但是为超过 10 个参数创建 std::bind 似乎并不容易。

【问题讨论】:

  • +1 很好的问题。

标签: c++ function-pointers member-function-pointers


【解决方案1】:

std::functionstd::bind 和 lambda 是您正在寻找的。总之,函数指针是很不好的东西,应该被烧死。总之,std::function 可以存储任何可以使用正确签名调用的函数对象,您可以使用std::bind 或 lambda 生成一个函数对象,以便快速轻松地调用您的成员函数。

编辑:那么您只需要滚动您自己的支持 10 个以上参数的 std::function 等效项。

【讨论】:

  • 我忘了说。我尝试更改为 std::function,但我原来的函数有超过 10 个参数(它是一个 Fortran 子例程)。
  • @AbelSiqueira:获得更好的编译器(或添加标志-std=c++11):C++ 2011 支持可变参数,您可以传入任意数量的参数。如果这对您不起作用,只需键入带有适当数量参数的 std::function&lt;Signature&gt; 版本。
  • 函数指针有合适的时间和地点。它们可能并不总是最好的解决方案,但在某些情况下肯定无法做到。
  • @DietmarKühl:抱歉,找不到std::function&lt;Signature&gt; 是什么,或者它是如何工作的。你能指出方向或举一个例子吗?不能使用 -std=c++11,或者改变编译器。
  • @Siqueira: std::function&lt;T&gt; 并不是什么神奇的东西(我用Signature 表示模板参数实际上是一个函数签名)。您可以实现相同的逻辑并根据需要提供尽可能多的参数。这并不复杂,主要是打字练习。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多