Pregunta

Tengo un código similar a este en mi aplicación:

class A
{
  public: int b;
}

class C
{
  public: int d;
}

void DoThings (void *arg1, MYSTERYTYPE arg2);

A obj_a;
C obj_c;

DoThings(&obj_a, &A::b);
DoThings(&obj_c, &C::d);

La pregunta es - ¿Qué MYSTERYTYPE ser?ni void* ni int trabajo, a pesar de que el valor &a::b se imprime bien si la salida es a través de un printf.

Aclaraciones:Sí, &A::b se define en C++.Sí, estoy tratando de conseguir el desplazamiento de un miembro de la clase.Sí, estoy siendo complicado.

Editar:Oh, puedo usar offsetof().Gracias de todos modos.

¿Fue útil?

Solución

Usted tiene un miembro de datos puntero a dos las clases no relacionadas.Bien, usted no puede encontrar un tipo común que puede sostener los dos punteros.Esto sólo funcionará si el parámetro de la función es un miembro de datos puntero a un miembro de la derivada, ya que está garantizado para contener el miembro demasiado, si una base contiene:

struct a { int c; }; struct b : a { }; int main() { int b::*d = &a::c; }

Actualización:Creo que debería escribir razón por la que el se convierte de a::* a b::* de forma implícita.Después de todo, normalmente tenemos b* a a* !Considere la posibilidad de:

struct a { };
struct b : a { int c; };
struct e : a { };
int main() { int a::*d = &b::c; e e_; (e_.*d) = 10; /* oops! */ }

Si lo anterior sería válido, usted realmente mucho la pata.El de arriba es no válido, porque la conversión de b::* a a::* no es implícita.Como se puede ver, se ha asignado un puntero a b::c, y entonces podríamos eliminar la referencia utilizando una clase que no contienen a todos!(e).El compilador aplica este orden:

int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }

Es falla para compilar ahora, porque e no es derivada de la b, la clase de los estados puntero puntero pertenece.Buenas!El siguiente, sin embargo, es muy válida y que recoge, de curso (cambiado las clases a y b):

struct a { int c; };
struct b : a { };
struct e : a { };
int main() { int e::*d = &a::c; e e_; (e_.*d) = 10; /* works! */ }

Para hacer que funcione para su caso, usted tiene que hacer su función de una plantilla:

template<typename Class>
void DoThings (int Class::*arg) { /* do something with arg... */ }

Ahora, el compilador de la auto-deducir la clase de derecho que el miembro de que se puntero también pertenece.Tendrá que pasar a la instancia junto con el miembro puntero para hacer uso de ella:

template<typename Class>
void DoThings (Class & t, int Class::*arg) { 
    /* do something with arg... */ 
    (t.*arg) = 10;
}

Si usted sólo desea establecer algunos de los estados que ya sabes en el momento de escribir DoThings, los siguientes sufijos:

template<typename Class>
void DoThings (Class & t) {  
    t.c = 10;
}

Otros consejos

Simplemente están tratando de llamar a una función con la dirección de un entero que pasa a vivir en el interior de un A o un C objeto?En ese caso, Jeff McGlynn la respuesta es el camino a seguir.

De lo contrario, si realmente están tratando de hacer algo complicado, que requiere de C++'s raro puntero-a-miembro de las instalaciones (y casi seguro que no):

Desde clases A y C no están relacionados, usted necesitará una plantilla de función para controlar ambos:

template <typename T>
void DoThings(int T::*x);

Si C fue en realidad se deriva de A, el siguiente trabajo:

void DoThings(int A::*x);

& amp; A :: by & amp; C :: d no tienen sentido, no hay una dirección asociada. ¿Estás tratando de obtener el desplazamiento del miembro?

¿Estás seguro de que no quieres algo como lo siguiente?

DoSomething(&obj_a,&obj_a.b);

Si usa plantillas como sugiere j_random_hacker, y el compilador conoce el tipo de cada clase en el punto donde llama a la función, la respuesta literal a su pregunta es " template <typename CLASS> void DoThings (CLASS * object, int CLASS::*MEMBER) " ;.

Así es como encajaría en su ejemplo:

#include <iostream>

class A {
public: 
    int b;
};

class C {
public: 
    int d;
};

template <typename CLASS>
void DoThings (CLASS * object, int CLASS::*MEMBER)
{
    std::cout << object->*MEMBER << std::endl;
}

A obj_a = { 2 };
C obj_c = { 4 };

int main (int argc, const char * argv[])
{
    DoThings(&obj_a, &A::b);
    DoThings(&obj_c, &C::d);
    return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top