Såvidt jeg har forstået så skal const operatoren kaldes (ANSII C++) hvis man laver noget i stil med: T val = (const T&)Table[\"blah\"]; Men det sker ikke!!!!!! Den kalder ALTID den, der ikke er const! - og det er ligemeget hvilken rækkefølge jeg erklærer dem i.
Hvad skal jeg gøre for at instruere compileren (g++) til at bruge const operatoren?
jeg undrer mig at compileren ikke klager, basalt set er de ens. ifølge standarden kan overloadede funktioner ikke skælnes på retur typen, så den eneste forskel på de to funktioner er at du har højt og hellig lovet ikke at gøre noget i den ene (pille i data).
Hvis det er standard, hvorfor kalder den så ikke ? :-)
Hvis det er C++, burde du så ikke anvende C++ cast operatorerne i stedet for C\'s, eller vil det ikke gøre en betydelig forskel ? static_cast<const T&>(Table[\"blah\"]);
Måske er det bare en compiler fejl (bug) ?
Jeg ved ikke som visual c++ 5 er ansi c++ 100% men følgende ,
class test { int& operator[]( char param ); const int& operator[]( char param ) const;
int a; };
giver følgende fejl: overloaded functions only differ by return type
stringbuffer >> Det du har lavet er som cries skriver overloading af en operator - og det kræver at der er forskel i parametrene til funktionen. Return-type bliver IKKE -gentager IKKE- betragtet i forhold til overloading. Derfor er det heller ikke muligt at lave dette her:
hvilke enhver compiler bør brokke sig over. Jeg må jo spørge mig selv, hvorfor du overhovedet vil have en const variant - den er jo til fulde dækket at du \"non-const\" variant. Hvis det er for at beskytte char* variablen, skulle du kunne gøre dette:
idet const char* og char* ikke er det samme. Når du kalder operatoren skal du selv \"vælge\" hvilken af de to du vil bruge vha. const modifieren:
T val = Table[const \"blah\"];
Du kan bl.a. i C++ Builder overstyre typen af char* (\'unsigned char\' eller noget i den stil) hvilken kunne betyde at din compiler oversætter dine function call inden compilering, og at de to funktioner derfor ender med at være ens.
Det er ikke mit argument, jeg skal beskytte, men det objekt, operatoren kaldes på.
Hvis man kalder operatoren med et index, som ikke findes i tabellen i forvejen, bliver denne oprettet (af den operator, der ikke er const). Det er nødvendigt for at lave en assignment, f.eks. Tabel[\"noget\"] = 112;
Derimod er der kun brug for en const returtype når man assigner den anden vej:
int noget = Tabel[\"noget\"];
Det er såvidt jeg ved derfor, man laver denne overloading, og derfor brokker en fornuftig compiler sig ikke over det.
Hvis man f.eks. vil tjekke en masse ord for om de findes i tabellen, vil der blive oprettet en ny celle i tabellen for hvert nyt ord. Det er da lidt tåbeligt når det er almindeligt kendt at en hashtabel mister meget af sin effektivitet når fyldningsfaktoren bliver over 80%.
Hvis man kan bruge en operator ... [] const vil tabellen ikke vokse. Det er bare underligt at compileren ikke bruger den.
stringbuffer >> ??? Det forstod jeg ikke en meter af.
Du kan da ikke checke forekomsten af et givent ord, ved at lave et ASSIGNMENT på den !?! I øvrigt er det da dig der styrer hvordan indexet \"noget\" bliver anvendt. Hvis du skal checke om et givent ord er i din tabel, skal du da lave dette check:
if (Tabel[\"et givent ord\"] != 0) { // Er i tabellen. Tabel[\"et givent ord\"] += 1; } else { // Ordet er ikke i tabellen. }
Idet jeg antager at din hash-tabel indeholder elementer der ser sådan her ud:
typedef struct { string ord; int refCount; } hashTblElm;
soepro >> !!! jeg kan da ikek gøre for at du ikke forstår
Jeg har da ikke nogen sted skrevet at jeg vil tjekke forekomsten ved at lave en assignment, faktisk gør jeg det lige præcis som du skriver ovenfor.
Men lige så snart man laver noget i stil med if (Tabel[\"ord\"] != 0) ... bliver der oprettet en tabel element til dette ord. Selvom man bare vil læse en const værdi!
Koden virker fint, det kan ikke lade sig gøre at lave en [] operator, der ikke opretter et nyt tabel element hvis denne skal kunne bruges sådan: Tabel[\"Nyt element\"] = noget; Men det er ikke nødvendigt at oprette et nyt element i tabellen når man gør det her: noget = Tabel[\"ord\"];
Men OK, hvis du virkeligt SKAL overbevises, er koden her:
// Illegal size if ( the_no_elements < 1 ) { printf(\"Hashtable has invalid bounds\\n\"); exit(1); }
// Allocate P_Cell vactor, that is the hash table itself if ((the_p_cell_vec = new P_Cell[the_no_elements]) == NULL) { perror(\"Cannot create hashtable\"); exit(1); }
// Initialize all elements to NULL for(int i=0; i<the_no_elements; i++) the_p_cell_vec[i] = NULL; }
template <class T> const T& Hashtable<T>::operator[]( const char* key_value ) const { unsigned int h = hash(key_value); printf(\"Subscript const\\n\"); P_Cell p = the_p_cell_vec[h]; while ( p != NULL ) { if ( !strcmp(p->key_value, key_value) ) return p->value; p = p->p_next; } // Return default value of datatype return T_Default; }
template <class T> T& Hashtable<T>::operator[]( const char* key_value ) { unsigned int h = hash(key_value); P_Cell *p = &the_p_cell_vec[h]; // Search the chain at position h in the vector while ( *p != NULL ) { if ( !strcmp((*p)->key_value, key_value) ) return (*p)->value; p = &((*p)->p_next); }
// Non existing key: create cell and chain in if ((*p = new Cell(key_value)) == NULL) { perror(\"Cannot allocate storage in hashtable\"); exit(1); } count++;
// It\'s the first insert if (first_cell == NULL) { first_cell = *p; last_insert_cell = *p; } else { // This one becomes the last inserted cell last_insert_cell->p_nextval = *p; last_insert_cell = *p; } return (*p)->value; }
template <class T> const char* Hashtable<T>::First() { // Point to first inserted value current_cell = first_cell; if (current_cell != NULL) return current_cell->key_value; return NULL; }
template <class T> const char* Hashtable<T>::First(T& val) { // Point to first inserted value current_cell = first_cell; if (current_cell != NULL) { val = current_cell->value; return current_cell->key_value; } return NULL; }
template <class T> const char* Hashtable<T>::Next() { // If not already at last cell if (current_cell != last_insert_cell) { // Move to next cell current_cell = current_cell->p_nextval; return current_cell->key_value; } return NULL; }
template <class T> const char* Hashtable<T>::Next(T& val) { // If not already at last cell if (current_cell != last_insert_cell) { // Move to next cell current_cell = current_cell->p_nextval; val = current_cell->value; return current_cell->key_value; } return NULL; }
template <class T> void Hashtable<T>::list() { int h = 0; while ( h < the_no_elements ) { P_Cell *p = &the_p_cell_vec[h];
// Print content of this chain printf(\" (%d)C %d\\t\", the_p_cell_vec[h], h); while ( *p != NULL ) { printf(\" (%d) [%s]\", *p, (*p)->key_value); p = &((*p)->p_next); } printf(\"\\n\"); h++; } }
template <class T> int Hashtable<T>::hash(const char* key) { unsigned int i, h = 0, g; for (i=0; key[i] != 0; i++) { h = (h << 4) + key[i]; if (g = h & 0xf0000000) { h ^= g >> 24; h ^= g; } } return h % the_no_elements; }
LOL kom til at bytte om på kommentarerne ved de 2 [] operatorer i hashtable.h da jeg byttede om på dem med cut\'n\'paste. Der skal selvfølgelig byttes om på kommentarerne :) Anyway, koden bliver ikke anderledes af den grund.
Provide access to the field\'s value. To be sure a const function is called, it is best to use get(). For a non-const object, a non-const function is called, even if used as an rvalue.
Svaret er altså at man kan ikke bruge en const operator medmindre man opretter et const kopi af en eksisterende tabel og bruger indeks operatoren på den - så bliver dens const operator kaldt.
Man kan tilsyneladende ikke (desværre...) få compileren til selv at finde ud af hvornår den skal bruge hvilken version af operatoren, selvom det burde være nemt nok at lave en option til det... det er jo nemt at se hvad der er rvalue og hvad der er lvalue.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.