Verifique se x é derivado de y via tipoid
Pergunta
Preciso converter ponteiros para long (sendMessage ()) e quero verificar com segurança se a variável está correta no outro lado. Então, eu estava pensando em fazer dinâmico_cast, mas isso não funcionará em classes que não são virtuais. Então pensei em fazer o TypeID, mas isso funcionará até que eu passe um VAR derivado como base.
Existe alguma maneira de verificar se o ponteiro é o que estou esperando durante o tempo de execução? Existe uma maneira de usar o TypeID para ver se um ponteiro é um tipo derivado de uma base específica?
Solução
Se tudo que você tem é um long
, então não há muito que você possa fazer. Não existe uma maneira geral de determinar se um número arbitrário representa um endereço de memória válido. E mesmo que você saiba que é um endereço de memória válido, não há como determinar o tipo de coisa que o ponteiro aponta. Se você não pode ter certeza do tipo real da coisa antes de seu endereço ser lançado para long
, então você não pode ter certeza de que será seguro lançar o long
Para qualquer tipo que você planeja lançá -lo.
Você só precisará confiar que o remetente da mensagem enviou um valor válido. O melhor que você pode fazer é tomar algumas precauções para reduzir as consequências para o seu próprio programa quando receber um valor falso.
Outras dicas
Sua referência a SendMessage()
faz com que eu pareça como o MS Windows é sua plataforma e depois o Regras para o uso de ponteiros (Windows) é a leitura recomendada. Detalha o PtrToLong
e PtrToUlong
Funções e outras coisas que a Microsoft fornece para você em situações como essa.
Você não pode usar o tipoID. Isso resultará em uma violação de acesso se você receber lixo em vez de um ponteiro válido, para que seu cheque seja absurdo.
O que você deve fazer é envolver sua sendmessage e o código que processa a mensagem em uma única interface de tipo. Dessa forma, você não poderá passar coisas inesperadas para a SendMessage e não precisará de nenhum cheque no lado recebido.
O sistema de tipo C ++ funciona no horário de compilação. Depois de lançar um ponteiro por muito tempo, você perde todas as informações do tipo. Um longo é tanta bits na memória; Não há como identificar que estava apontando para um objeto.
Ptlib ( http://sourceforge.net/projects/opalvoip/ ) usa uma macro pclassinfo para definir as relações entre as classes. Isso fornece funções como IsDescendente e GetClass.
Você provavelmente poderia implementar algo semelhante.
Dynamic_cast funciona verificando a assinatura da tabela de métodos virtuais. Se você não possui métodos virtuais, não tem VMT, portanto, como diz o Dynamic_cast, não funcionará. No entanto, se você não tiver VMT, não tem absolutamente nenhum conhecimento sobre o objeto que está sendo apontado.
Sua melhor aposta é exigir que os ponteiros sejam para aulas com pelo menos um método virtual, mesmo que seja um manequim. O elenco dinâmico funcionará então.
Ainda não entendo o que é sua pergunta.
- Se for, se você pode ou não ter certeza de que o lançamento para um longo e as costas produzirá o mesmo valor, veja Verificando com segurança o tipo de variável
Dadas as "regras para usar ponteiros" no local do MS, o outro respondente vinculado, o tipo certo a ser lançado éUINT_PTR
. Então você fazUINT_PTR v = reinterpret_cast<UINT_PTR>(ptr);
lançar -se para um tipo integral e fazer o inverso para lançá -lo de volta ao ponteiro novamente. O padrão C ++ garante que o valor original seja restaurado. (Veja o link que dei acima para minha explicação disso). A propósito, esse site da Microsoft também diz que o WPARAM e o LPARAM mudam seu tamanho, dependendo da plataforma. Então você poderia usar essa variávelv
eSendMessage
isto. - Se é como você pode verificar por outro lado se o ponteiro (convertido em algum tipo de ponteiro) aponta para algum objeto, a resposta é você não pode. Como você aparentemente não tem certeza de qual tipo de ponteiro foi usado para enviá -lo, você não pode verificar no lado receptor o que o tipo dinâmico que o ponteiro aponta é. Se você souber o tipo que o ponteiro tinha no lado do remetente, seu cheque não seria necessário em primeiro lugar.
No Windows, o MFC fornece um método para verificar se um determinado ponteiro está apontando para um local de memória válido (isso é feito prendendo o Segfault). Não me lembro do nome da função, mas está lá. Ainda assim, ele não garante que o conteúdo da memória apontado seja válido. Ainda pode ter VMT inválido e travar seu código. Claro, você pode prender o segfault (Veja MS Base de Conhecimento)
Quanto à verificação, se algo pertence a um tipo, você deve ter uma classe base para começar. Se você fizer o destruidor da classe base "virtual", todas as classes derivadas terão VMTs.
Se você precisar evitar o VMT a todo custo, precisa ter algum tipo de descrinação que informe com o que você está lidando, como o tipo de evento nos eventos do MS Windows.