Pergunta

Eu tenho código semelhante a este no meu aplicativo:

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

A questão é - O que MYSTERYTYPE deve ser? nem * vazio nem trabalham int, apesar do valor & A :: b sendo impresso muito bem se você saída através de um printf.

Esclarecimentos: Sim, & A :: b é definido em C ++. Sim, eu estou tentando obter o deslocamento para um membro da classe. Sim, eu estou sendo complicado.

Edit: Oh, eu posso usar offsetof (). Obrigado na mesma.

Foi útil?

Solução

Você tem um ponteiro membro de dados para duas classes não relacionadas. Bem, você não consegue encontrar um tipo comum que pode conter ambos os ponteiros. Ele só irá funcionar se o parâmetro de função é um ponteiro membro de dados a um membro da derivada, porque é garantido para conter o membro também, se uma base contém:

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

Atualizar : Eu acho que eu deveria escrever porque os convertidos acima de a::* para b::* implicitamente. Afinal de contas, nós geralmente temos b* para a*! Considere o seguinte:

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

Se o acima seria válida, você seria realmente muito estragar. A descrição acima é não válido, porque a conversão de b::* para a::* não é implícito. Como você vê, temos atribuído um ponteiro para b :: c, e então poderíamos desreferenciava-lo usando uma classe que não contê-lo em tudo! (e). O compilador impõe esta ordem:

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

não para compilar agora, porque e não é derivado de b, a classe o ponteiro ponteiro membro pertence. Boa! A seguir, no entanto, é muito válido e compila, é claro (mudou aulas a e 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 fazê-lo funcionar para o seu caso, você tem que fazer a sua função de um modelo:

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

Agora, o compilador auto-deduzir a classe certa de que o dado ponteiro de membro pertence também. Você terá que passar a instância ao lado do ponteiro membro de realmente fazer uso dele:

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

Se você quiser apenas para definir algum membro você já sabe no momento que você escreve DoThings, os seguintes sufixos:

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

Outras dicas

Você está simplesmente tentando chamar uma função com o endereço de um inteiro que acontece a viver dentro de um A ou um objeto C? Nesse caso, a resposta de Jeff McGlynn é o caminho a percorrer.

Caso contrário, se você realmente está tentando fazer algo complicado que exige instalação estranho ponteiro-para-membro de C ++ (e você quase certamente não são):

Uma vez que as classes A e C não estão relacionados, você vai precisar de uma função de modelo para lidar com ambos:

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

Se C foi derivado realmente A, o seguinte iria funcionar:

void DoThings(int A::*x);

& A :: b e & C :: d são sem sentido, não existe nenhum endereço associado. Você está tentando obter o deslocamento do usuário?

Você tem certeza que não quer que algo como o seguinte?

DoSomething(&obj_a,&obj_a.b);

Se você usar modelos como j_random_hacker sugere, e o compilador sabe o tipo de cada classe no ponto onde você chamar a função, a resposta literal à sua pergunta é "template <typename CLASS> void DoThings (CLASS * object, int CLASS::*MEMBER)".

Aqui está como ele iria se encaixar em seu exemplo:

#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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top