Como posso descobrir o tamanho real da classe meu C ++?
Pergunta
Eu estou trabalhando em uma tarefa de casa em que eu sou obrigado a matrizes uso de char em vez de cordas e qsort / bsearch. Na minha chamada para bsearch abaixo, eu sei eu estou passando o tamanho errado de entrada, mas não tenho certeza de como obter o tamanho real, e minha função compareEntries não é, portanto, encontrar os objetos certos .
Alguém pode me ajudar a entender o que eu estou perdendo?
#include <iostream>
using namespace std;
typedef Entry* EntryPtr;
class Dictionary
{
public :
Dictionary( const char *filename );
~Dictionary();
const char *lookupDefinition( const char *word );
private :
int m_numEntries;
EntryPtr *m_entries;
static int compareEntries(const void *leftSide, const void *rightSide);
};
int Dictionary::compareEntries(const void *leftSide, const void *rightSide)
{
EntryPtr lside = (EntryPtr) leftSide;
EntryPtr rside = (EntryPtr) rightSide;
return strcmp(lside->Word, rside->Word);
}
const char *Dictionary::lookupDefinition(const char *word)
{
if (m_numEntries == 0)
return 0;
EntryPtr result = (EntryPtr) bsearch(word, m_entries,
m_numEntries, sizeof(m_entries[0]), Dictionary::compareEntries);
return result->Definition;
}
class Entry
{
public:
Entry(const char *line);
char *Word;
char *Definition;
};
int main()
{
Dictionary dict( "C:\\path\\file.txt" );
dict.lookupDefinition("chair");
return 0;
}
Solução
Por que não funciona sizeof(Entry)
?
mudou de novo - Eu acho que o tamanho deve ser o tamanho do ponteiro ....
EntryPtr tmp = new Entry("");
tmp->Word = word;
EntryPtr result = (EntryPtr) bsearch(tmp, m_entries,
m_numEntries, sizeof(EntryPtr), Dictionary::compareEntries);
Outras dicas
O problema é que a função do comparador utilizado em espera bsearch
word
para ser do tipo Entry*
(ou m_entries
para ser do tipo char**
).
Você sabe que bsearch
requer entrada classificada, certo?
aparência sizeof(m_entries[0])
perfeitamente bem para mim.
Edit: Agora eu vejo o problema. Sua classe dicionário contém uma matriz de ponteiros. O problema está na função compareEntries, onde você elenco passou ponteiros para EntryPtr
; você precisa lançá-los para EntryPtr *
vez.
Edit 2: Como apontado por Amit Kumar , você também necessidade de alterar a chave de parâmetros que você enviar para bsearch, ou você precisa perceber que os ponteiros que você recebe em compareEntries não estão apontando para os mesmos tipos e vai precisar de dois typecasts diferentes.
sizeof (Entry) iria funcionar. Principalmente sizeof deve ser usado com o tipo, em vez de uma instância.
sizeof (Entry)
É preferível
Entrada e;
sizeof (e);
ou
Entrada * e;
sizeof (* e);
todos dão o mesmo resultado.
#include "stdio.h"
class Entry {
double e;
int i;
};
int main() {
Entry e;
printf("%d\n", sizeof(e));
printf("%d\n", sizeof(Entry));
printf("%d\n", sizeof(*(&e)));
return 0;
}
Leia a manual do cuidado.
Um resumo dos pontos feitos por outras pessoas, bem como mais algumas questões:
-
O uso de sizeof está correto.
-
Você deve passar um ponteiro para a entrada que contém a chave que você deseja procurar.Na verdade, a chave pode ser qualquer coisa, e ele vai ser passado para a função de comparação como o primeiro argumento , e você só precisa lançar ambos os argumentos de direito tipos. (A função de comparação ainda deve corresponder à ordem os itens foram classificadas segundo.) -
Os moldes da função de comparação não estão corretas. A função de comparação recebe um ponteiro para o elemento (que no seu caso é um ponteiro para entrada, portanto, a função de comparação recebe ponteiros para ponteiros para Entry).
-
Você converter o resultado para o tipo errado. Mais uma vez a função retorna um ponteiro para um elemento na matriz (ponteiro para a entrada de ponteiro).
-
Você não verificar se o resultado é NULL, se a chave não estar lá.
-
Você provavelmente poderia desistir de um nível de engano (você realmente precisa de uma matriz de ponteiros em vez de um conjunto de entradas?)
-
Você deve tomá-lo como um bom exemplo do que as pessoas querem dizer quando falam sobre as virtudes do tipo de segurança: em seu código praticamente todos os tipos se misturam e você está fazendo coisas erradas com tipos errados, contudo não uma única queixa do compilador. Isso é o que você ganha se você mexer com
void*
, se você não sabe exatamente o que você está fazendo.
Para se divertir, ter uma matriz de ponteiros é preciso uma quantidade ridícula de engano para obter um resultado:
#include <cstdlib>
#include <string>
#include <iostream>
int compare_string(const void* a, const void* b)
{
return ((const std::string*)a)->compare(**(const std::string**)b);
}
int main()
{
std::string a("a"), b("b"), c("c");
std::string* array[3] = { &a, &b, &c };
std::string key = "b";
std::string** result = (std::string**)bsearch(&key, array, 3, sizeof(std::string*), compare_string);
if (result) std::cout << **result << '\n';
}
IMO, que levaria menos tempo para implementar seu próprio bsearch tipo seguro, do que leva a descobrir tudo isso e tê-lo testado e depurado.