Pregunta

Decir que tengo una clase:

class A
{
public:
  void doSomething();
}

Cuando doSomething hace algo que se basa explícitamente en el estado interno de la instancia de A.

Ahora, tengo una situación en la que tengo un montón de cosas de tipo A por ahí, pero yo sólo quiero llamar doSomething de un subconjunto estricto de ellos, así que quiero pegarlas en la lista. En particular, lo que realmente quiero hacer es pegarse a los punteros doSomethings individuales () en la lista.

¿Puedo hacerlo también os anuncio que, como:?

std::list<(A::*)()> aDoSomethings;

leí esta entrada , tiene sentido y lo haré ir por ese camino si necesito.

¿Fue útil?

Solución

Parece que usted está confundido acerca de cómo miembro de punteros a funciones de trabajo. Para una clase dada, sólo hay una única instancia de cualquier función dada. Se diferencian por el uso de la this parámetro implícito. Básicamente, se puede pretender que tiene la siguiente asignación.

struct Struct { void Function(); }
Struct a;
a.Function();

se convierte en

struct Struct { }
void Function(Struct* this);
Struct a;
Function(&a);

Así que si usted tiene un montón de objetos Struct, y al que desea llamar Function en un pequeño conjunto de ellos, no almacenar Function, almacenar Struct.

Los punteros a funciones miembro son utilizados cuando se tiene múltiple funciones, que desea llamar selectivamente. Así que si usted tiene dos funciones en su clase, los cuales no toman parametros y volverá vacía, void (Struct::*)() puede apuntar a cualquiera de ellos. Pero aún apunta a una función específica, de los cuales sólo hay una. Todavía es necesario para proporcionar el parámetro this.

struct Struct {
  Struct(int v) : value(v) { }
  void One() { cout << "one: " << value << endl; }
  void Two() { cout << "two: " << value << endl; }
  int value;
};

int main()
{
  std::vector<Struct> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  std::vector<void (Struct::*)()> f;
  f.push_back(&Struct::One);
  f.push_back(&Struct::Two);
  f.push_back(&Struct::One);

  for(int i = 0; i < 3; ++i)
    (v[i].*f[i])();
}  

No es el mejor ejemplo, pero se pone el punto a través. Usted puede mezclar y combinar objetos, con funciones miembro.

* Editar: Un ejemplo sin contenedores conseguir en el camino

Struct a(5), b(10);
void (Struct::*one)() = &Struct::One;
void (Struct::*two)() = &Struct::Two;

(a.*one)();
(b.*one)();
(a.*two)();
(b.*two)();

Tenga en cuenta el paréntesis extra. a.*one() es insuficiente.

Otros consejos

¿Usted ha considerado el enfoque orientado a objetos simple:

struct Can_Do_Something
{
    virtual void doSomething() = 0;
};

class A : public Can_Do_Something
{
    ...
};

std::list<Can_Do_Something*> my_list;

my_list[n]->doSomething();

Este es el mantenimiento de forma restrictiva el acceso a la parte de la interfaz de A - heredada a través del tipo Can_Do_Something - que va a acceder a través de la lista. Es documentos y hace cumplir esa restricción.

Si usted tiene una preferencia por algo más cercano a su visión original, considere ...

#include <iostream>
#include <vector>
#include <boost/function.hpp>

struct A
{
    A(int n) : n_(n) { }

    int f(int x) { std::cout << "A::f() this " << (void*)this
                           << ", n_ " << n_
                           << ", x_ " << x << '\n'; }

    int n_;
};

int main()
{
    typedef boost::function<int (int n)> Function;
    typedef std::vector<Function> Functions;

    Functions functions;
    A a1(1), a2(2), a3(3);

    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a1));
    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a2));
    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a3));

    for (Functions::iterator i = functions.begin();
            i != functions.end();
            ++i)
        (*i)(42);
}

A continuación, impulso :: función se utiliza para crear una devolución de llamada a las funciones específicas que le interesan.

Un puntero a función miembro no tiene un puntero a una instancia particular:. En él se describe cómo llamar a una función miembro con una cierta firma dado un puntero this y los parámetros

En su lugar, puso punteros a los objetos que se preocupan en la lista, y luego iterar sobre esa lista, llamando doSomething en cada artículo.

Se debe comprobar fuera de impulso :: función y boost :: bind.

Sí, es probable que desee algo como:

#include <vector>
#include <iostream>
#include <string>

using namespace std;

class A {
  string m_name;

  public:
    A(const string& name) : m_name(name) {} 
    void doSomething() { cout << m_name << "::doSomething()" << endl; }
};

int main(void) {
  A f1("f1");
  A f2("f2");
  A f3("f3");
  A f4("f4");
  vector<A*> foo_list;
  foo_list.push_back(&f1);
  foo_list.push_back(&f3);

  for (vector<A*>::iterator it = foo_list.begin(); it != foo_list.end(); *it++) {
    static_cast<A*>(*it)->doSomething();
  }

  return 0;
}

Si mi interpretación es correcta, usted quiere tener una lista de punteros a miembro de las funciones que tienen que ser doSomething ()?

A continuación, puede tener una lista de punteros de función a un miembro de su clase, pero tendrá que proporcionar el objeto asociado con ella, ¿por qué no simplemente mantener una lista de (punteros a) los objetos?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top