Конструкторы с функциями в качестве аргументов в C ++

StackOverflow https://stackoverflow.com/questions/19848437

Вопрос

У меня есть несколько объектов, которые переменные полагаются на разные функции. Чтобы выразить это различными словами: существует несколько типов функций, на которые полагаются переменные в объекте, но должно быть несколько объектов с теми же из этих функций. Для получения большего разрешения я попытался привести пример (который не работает).

#include <iostream>

class A
{
  double size;

  A( double (*f)() )
  {
    size = (*f)();
  };
};

double fun1()
{
  return 42.0;
}


int main()
{
  A a = A( &fun1() );

  std::cout << a.size << std::endl;
}

Это, конечно, минимальный пример. Размер переменной зависит от определенной функции, которая должна передаваться в качестве аргумента в класс. Представить fun1 а также fun2 как разные виды генераторов случайных чисел.

Я думаю, что идеоматическим способом в C ++ будет класс, который удерживает переменную, а классы, унаследованные от нее, изменяются этой функцией, которая отличает объекты (пожалуйста, исправьте меня, если я ошибаюсь с этим предположением). Но мой вопрос:

Есть ли возможность реализовать какой-то конструктор высшего порядка? Если это так, пример был бы неплохо.

PS: Если бы я использовал некоторые технические термины неправильно, я был бы рад исправить.

Это было полезно?

Решение

Изменить на:

A( double (*f)() )
{
    size = f();
};

А также:

A a = A( fun1 );

Когда ты проходил &fun1() Это пыталось вызвать функцию, а затем взять адрес ее результата. То, что вы на самом деле хотели, было самого указателя функции, который хранится в fun1.

Другие советы

Этот пример не является бессмысленным, потому что вы не сохраняете указатель функции для последующего использования. Вы можете переписать это просто на

class A
{
    double size;

    A(double sz) {
        size = sz;
    };
};

double fun1()
{
    return 42.0;
}


int main()
{
    A a = A(fun1());
    std::cout << a.size << std::endl;
}

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

#include <iostream>

class A {
public:
    template<typename F>
    explicit A(F&& f) : size(f()) {

    };

    double size;
};

double fun1() {
    return 42.0;
}

int main() {
    A a(&fun1);
    std::cout << a.size << std::endl;
}

Похоже, вам нужна только сама функция. Ты почти получил это. Вот правильный синтаксис:

typedef double (*functype)();

void foo(functype f) {
    cout << f();
}

double bar() {
    return 2.39;
)

foo(bar); // don't call bar here, just pass it as address.

Вы также можете объявить Foo следующим образом:

void foo(double (*f)());

Функции не являются первоклассными объектами в C ++, поэтому единственным способом создания закрытия с некоторыми переменными (например, если вы хотите носить функцию или вызвать нестатическую функцию-член), являются функторы (объекты с перегруженным оператором () ) Есть несколько способов получить такой объект:

  1. Определите его самостоятельно, храните все необходимые переменные в полях и передайте его как аргумент функции.
  2. Используйте функции Lambda C ++ 11 и функция Std ::
  3. Используйте Boost :: Function и Boost :: Bind.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top