Pergunta

Se o seguinte do C ++ FAQ Lite for verdadeiro: "um nome de função decai para um ponteiro para a função" (como um nome de matriz decai para um ponteiro para seu primeiro elemento); Por que temos que incluir o Ampersand?

typedef  int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = &Fred::f;

E não apenas:

typedef  int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = Fred::f;

No segundo caso, Fred :: F é uma função e pode decair para um ponteiro para essa função.

Espero que essa pergunta não seja tão estúpida.

Foi útil?

Solução

Resposta original:

Porque uma função de membro não é uma função e um ponteiro de função de membro não é um ponteiro de função. Portanto, as regras de decaimento não se aplicam.

Além disso, existe tipo de função em C ++, mas não no tipo de função de membro. Portanto, você pode usar uma função em locais onde é esperado um ponteiro para função, mas não pode usar uma função de membro porque não existe, apenas ponteiro para membro da função. f no seu exemplo é uma função. Por outro lado, Fred :: F é ... bem, nada.

Além disso, eu argumentaria que "o nome de uma função pode decair ...". Não, o nome não pode fazer nada, um lvalue do tipo de função pode ser implicitamente convertido em um ponteiro em função, e essa é uma conversão de identidade no que diz respeito à resolução de sobrecarga

Editando para esclarecer minha resposta:

Toda expressão em C ++ tem um tipo e valor. Ocasionalmente, um valor de um tipo pode ser convertido em um valor de outro tipo. Essas conversões são classificadas para melhorar uma conversão que outra é principalmente para resolução de sobrecarga de função.

Um dos tipos de conversões é chamado de conversão LValue-para-avaliação. Quando um LValue aparece em um contexto em que é necessário um RValue, essa conversão ocorre. Normalmente, esse tipo de conversão não faz nada, por exemplo:

int i = 4, j = 5;
i = j;

Na segunda linha J é um LValue, mas é necessário um Rvalue aqui, então J é convertido em um RValue. Mas isso não é uma conversão observável, é? Mas há casos em que a conversão de LValue em valor pode ser observada. Aquilo é, Um lvalue de matriz de n t pode ser convertido em um valor do tipo T* cujo valor é o endereço do primeiro elemento da matriz e um lvalue do tipo "função com assinatura s" um ravalue do tipo "ponteiro para funcionar com a assinatura s", cujo valor é o endereço da função

Isso significa que, quando atribuímos uma função a um ponteiro para função, a função LValue é implicitamente convertida em seu endereço.

void f() {}
void (*p) () = f; //f is converted to rvalue

f é uma expressão e tem um tipo. O tipo de f é void()

Não existe esse tipo em c ++ como um member-functionExistem ponteiros para membros, mas não os membros funções. Estou falando, é claro, sobre funções não estatísticas. As funções estáticas funcionam da mesma maneira que as funções comuns, ou seja, você não precisa escrever &X::f, em vez disso, você pode escrever X::fPor quê? Porque x :: f tem uma função de tipo e a conversão acima mencionada ocorre. Se F não é o estático, no entanto, x :: f é do tipo ... o quê? Ah, sim, ele não tem um tipo e, portanto, não é uma expressão e, portanto, não tem valor e, portanto, esse valor não pode ser convertido em nada.

Citação do padrão: 5.3.1 Cláusula 3 Um ponteiro para membro é formado apenas quando um explícito e é usado e seu operando é um ID qualificado não fechado entre parênteses. [Nota: isto é, a expressão & (qualificado-ID), onde o ID qualificado está entre parênteses, não forma uma expressão do tipo "ponteiro para membro". Nem o qualificado-ID, porque não há conversão implícita de um ID qualificado para uma função não estática para o tipo "ponteiro para função de membro", como existe de um lvalue do tipo de função para o tipo "ponteiro para função" (4.3 ). Nem o ID não qualificado é um ponteiro para o membro, mesmo dentro do escopo da classe do ID não qualificado.

Espero que isso tenha sido mais claro ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top