Pergunta

Eu tenho alguns objetos cujas variáveis ​​dependem de funções diferentes.Para colocar em palavras diferentes:Existem vários tipos de funções nas quais as variáveis ​​do objeto dependem, mas deve haver vários objetos com as mesmas funções.Para mais esclarecimentos tentei dar um exemplo (que não funciona).

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

É claro que este é um exemplo mínimo.O tamanho da variável depende de uma determinada função que deve ser passada como argumento para a classe.Imagine fun1 e fun2 como diferentes tipos de geradores de números aleatórios.

Eu acho que a forma ideomática em C++ seria uma classe que contém a variável e as classes herdadas dela são modificadas por aquela função que difere os objetos (corrija-me se eu estiver errado com essa suposição).Mas minha pergunta é:

Existe alguma possibilidade de implementar algum tipo de construtor de ordem superior?Se sim, um exemplo seria bom.

p.s.:Se eu usei alguns termos técnicos errados, ficaria feliz em ser corrigido.

Foi útil?

Solução

Mudar para:

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

E:

A a = A( fun1 );

Quando você estava passando &fun1() que estava tentando chamar a função e depois pegar o endereço do seu resultado.O que você realmente queria era o próprio ponteiro de função, que está armazenado em fun1.

Outras dicas

Este exemplo não tem sentido porque você não salva o ponteiro de função para uso posterior.Você pode reescrever isso simplesmente para apenas

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

Sugiro escrever um modelo para que você possa passar qualquer ponteiro de função ou objeto de função.Isso permite que o compilador faça otimizações com mais facilidade, como inlining, em muitos casos, e é mais flexível.Você também não deve usar parênteses ao adquirir um ponteiro de função.

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

Parece que você precisa apenas que a própria função seja passada.Você quase conseguiu.Aqui está a sintaxe correta:

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.

Você também pode declarar foo da seguinte maneira:

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

Funções não são objetos de primeira classe em C++, então a única maneira de criar um fechamento com algumas variáveis ​​(por exemplo, se você deseja carregar a função ou chamar uma função de membro não estática) são functores (objetos com operador sobrecarregado() ).Existem várias maneiras de obter esse objeto:

  1. Defina você mesmo, armazene todas as variáveis ​​​​necessárias nos campos e passe-as como argumento da função.
  2. Use as funções lambda e std::function do C++ 11
  3. Use boost::function e boost::bind.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top