c++ указатель на нестатические функции-члены


Я прочитал много сообщений и ответов об указателях на нестатические функции-члены, но ни один из них не может решить мою проблему.
Поэтому я создал короткий пример, чтобы повторить мою проблему здесь: даже если этот пример может быть "решен" различными способами, для окончательного программного обеспечения важно сохранить структуру, как в Примере, спасибо.

Это заголовок класса " Funcs.h":

class Funcs
{
private:
  double a = 1, b = 2;

public:
  Funcs();
  ~Funcs();
  double Fun1(double X);
  double solver(double X0);
  double aaa(double(*fun)(double), double x0);
};

Это cpp класса " Funcs.cpp":

#include "Funcs.h"

using namespace std;

Funcs::Funcs()
{
}

Funcs::~Funcs()
{
}

double Funcs::Fun1(double X) {
  double f1 = a*X;

  return f1;
}

double Funcs::solver(double X0)
{
  double result;

  result = aaa(Fun1, X0);
  return result;
}

double Funcs::aaa(double(*fun)(double), double x0)
{
  return fun(x0);
}

И, Наконец, это и есть главное " главное.cpp":

#include <iostream>
#include "Funcs.h"

using namespace std;

int main() {
  double x0=1;
  double result;
  Funcs funcs;

  result = funcs.solver(x0);
  cout << result << endl;

  return 0;
}

Ошибка находится в методе Funcs:: solver, когда я вызываю " result = aaa (Fun1, X0);", потому что я не могу использовать указатель на Fun1, потому что это нестатический член. В то же время я не могу сделать его статическим, иначе переменная "a" не могла бы быть видна внутри статического метода.

Заранее благодарю за помощь.

3 7

3 ответа:

Проблема заключается в том, что вы пытаетесь передать указатель на функцию-член, в то время как ожидается, что указатель либо на функцию-член, либо на статическую функцию-член. И это разные типы.

Здесь " fun " - это указатель на функцию: double(*fun)(double).

И здесь это указатель на функцию-член класса Funcs: double(Funcs::*fun)(double)

Итак, вот как вы можете изменить свой код, чтобы заставить его работать.

class Funcs
{
  // all the rest is the same
  double aaa(double(Funcs::*fun)(double), double x0);
};

double Funcs::solver(double X0)
{
  // ...
  result = aaa(&Funcs::Fun1, X0);
  // ...
}

double Funcs::aaa(double(Funcs::*fun)(double), double x0)
{
  return (this->*fun)(x0);
}

Смотрите живой примерв Coliru .

Это может быть прекрасный способ пойти если вы хотите намеренно ограничить свой метод aaa, чтобы принимать только функции-члены Funcs как fun. Если вы также хотите передать функции, не являющиеся членами, или, например, лямбды в aaa, рассмотрите возможность использования std::function вместо этого.

Ваша проблема заключается в том, что указатель на функцию не совпадает с указателем на функцию-член. Прочитайте this для получения дополнительной информации и this для чистого способа записи указателя на функции-члены. Если вам нужно сохранить эту структуру, сделайте aaa статической или не являющейся членом функцией, которая принимает все, что ей нужно в качестве аргументов, или измените первый аргумент aaa на double(Funcs::*)(double) вместо double(*fun)(double). Вы даже можете перегрузить aaa для поддержки обоих видов использования.

На самом деле Funcs::Fun1 не является double(*)(double).

Любой нестатический метод имеет такую сигнатуру: return_type(*)(class_type* this, arguments...)

Давайте рассмотрим точные типы:

//first argument of `aaa` has type double(*)(double)
double aaa(double(*fun)(double), double x0);

double Funcs::Fun1(double X) {
  double f1 = a*X;

  return f1;
}

// Fun1 has type double(Funs::*)(double)
// i.e it's a method of Funs and it takes (implicitly) first argument
// which is `this` pointer

// so that how `aaa` must  look like
double aaa(double(Funs::*fun)(double), double x0)
{
    // special sytax
    *this.*fun(x0);
}

// and that how `solver` looks like
double Funcs::solver(double X0)
{
  double result;

  // get pointer to method
  result = aaa(&Funs::Fun1, X0);
  return result;
}

Если вы не знакомы с указателями на методы-проверьте this