polymorph object - why doesn't it work???

M

Mika Vainio

hi everybody,
i'm working on the following problem: i need to build a 26-nary tree to save
a data dictionary. every letter of the words is represented by a cell (cell
has a pointer-vector cell* children[26]). the last letter is a node
(node:cell, additional property "pagenr").
now: i understood the principals of polymorph objects and it worked fine
with the ususal examples. but in my case it does not! there is no
compilation or linking error and no error at runtime - at least not shown...
here's some code. maybe someone can give me some hints...


// Trie.cpp
//----------
(...)
void Trie::insert(char *word, int page)
{
// int value of first letter
int iword = ((int)word[0])-97;

insert_one(root->children[iword], word, page);
}

void Trie::insert_one(Cell* new_cell, char *word, int page)
{
if (new_cell == NULL) {
if (((int)word[1])-97 < 0) { // last letter
new_cell = new Node();

// new_cell->page = page;
}
else
new_cell = new Cell;

cout << typeid(new_cell).name() << " - ";
new_cell->display(); // virtual function in cell, cout pagenr in node
(...)

best regards,
mika
 
K

Karthik

Mika said:
hi everybody,
i'm working on the following problem: i need to build a 26-nary tree to save
a data dictionary. every letter of the words is represented by a cell (cell
has a pointer-vector cell* children[26]). the last letter is a node
(node:cell, additional property "pagenr").
now: i understood the principals of polymorph objects and it worked fine
with the ususal examples. but in my case it does not! there is no
compilation or linking error and no error at runtime - at least not shown...
here's some code. maybe someone can give me some hints...


// Trie.cpp
//----------
(...)
void Trie::insert(char *word, int page)
{
// int value of first letter
int iword = ((int)word[0])-97;
Try using macros instead of constants, as in 97 here.
insert_one(root->children[iword], word, page);
}

void Trie::insert_one(Cell* new_cell, char *word, int page)
{
if (new_cell == NULL) {
if (((int)word[1])-97 < 0) { // last letter
new_cell = new Node();

// new_cell->page = page;
}
else
new_cell = new Cell;

cout << typeid(new_cell).name() << " - ";
new_cell->display(); // virtual function in cell, cout pagenr in node
(...)
Do you have your own implementation of display function in 'Node'
class. It would be nice if you can mention the class hierarchy clearly
out here to understand things better.
 
J

John Harrison

Mika Vainio said:
hi everybody,
i'm working on the following problem: i need to build a 26-nary tree to save
a data dictionary. every letter of the words is represented by a cell (cell
has a pointer-vector cell* children[26]). the last letter is a node
(node:cell, additional property "pagenr").
now: i understood the principals of polymorph objects and it worked fine
with the ususal examples. but in my case it does not! there is no
compilation or linking error and no error at runtime - at least not shown...
here's some code. maybe someone can give me some hints...


// Trie.cpp
//----------
(...)
void Trie::insert(char *word, int page)
{
// int value of first letter
int iword = ((int)word[0])-97;

insert_one(root->children[iword], word, page);
}

void Trie::insert_one(Cell* new_cell, char *word, int page)
{
if (new_cell == NULL) {
if (((int)word[1])-97 < 0) { // last letter
new_cell = new Node();

// new_cell->page = page;
}
else
new_cell = new Cell;

cout << typeid(new_cell).name() << " - ";
new_cell->display(); // virtual function in cell, cout pagenr in node
(...)

best regards,
mika

Hard to say from the snippets given, but I would say that the problem is
incorrect use of pointers not polymorphism.
insert_one(root->children[iword], word, page);
void Trie::insert_one(Cell* new_cell, char *word, int page)
{

Think about that code. I think you are assuming that it will write a value
to root->children[iword] but it doesn't. You need something like this

root->children[iword] = insert_one(word, page);

Cell* Trie::insert_one(char *word, int page)
{
...
return new_cell;
}

john
 
M

Mika Vainio

hi karthik,
yes, i have my own display() implementation (cout << "Pagenr: " <<
new_cell->page << endl;). and here are all my header files.
best regards,
mika

// Cell.h
//-----------------
class Cell {
public:
Cell() {}
virtual ~Cell();
virtual void display() const;

char letter;
Cell* children[26];
};


// Node.h
//----------------
class Node : public Cell {
public:
Node() {}
int page;
void display();
Node* children[26];
};


// Trie.h
//----------------------------------
#include "Node.h"

class Trie {
public:
Trie() {
root = NULL;
root = new Cell;
for (int i = 0; i<26; i++)
root->children = NULL;
// root->page = 1;
root->letter = '\0';
}
void display();
void insert(char*, int);
int search(char*);
void erase(char*);

private:
Cell *root;
char *word;
void insert_one(Cell* new_cell, char *word, int page);
void display_one(Cell *top, char* prefix);
int search_one(Cell *&new_cell, char *word);
void erase_one(Cell *&new_cell, char *word);
};



Karthik said:
Mika said:
hi everybody,
i'm working on the following problem: i need to build a 26-nary tree to save
a data dictionary. every letter of the words is represented by a cell (cell
has a pointer-vector cell* children[26]). the last letter is a node
(node:cell, additional property "pagenr").
now: i understood the principals of polymorph objects and it worked fine
with the ususal examples. but in my case it does not! there is no
compilation or linking error and no error at runtime - at least not shown...
here's some code. maybe someone can give me some hints...


// Trie.cpp
//----------
(...)
void Trie::insert(char *word, int page)
{
// int value of first letter
int iword = ((int)word[0])-97;
Try using macros instead of constants, as in 97 here.
insert_one(root->children[iword], word, page);
}

void Trie::insert_one(Cell* new_cell, char *word, int page)
{
if (new_cell == NULL) {
if (((int)word[1])-97 < 0) { // last letter
new_cell = new Node();

// new_cell->page = page;
}
else
new_cell = new Cell;

cout << typeid(new_cell).name() << " - ";
new_cell->display(); // virtual function in cell, cout pagenr in node
(...)
Do you have your own implementation of display function in 'Node'
class. It would be nice if you can mention the class hierarchy clearly
out here to understand things better.
best regards,
mika
 
K

Karthik

Mika said:
hi karthik,
yes, i have my own display() implementation (cout << "Pagenr: " <<
new_cell->page << endl;). and here are all my header files.
best regards,
mika

// Cell.h
//-----------------
class Cell {
public:
Cell() {}
virtual ~Cell();
virtual void display() const;

char letter;
Cell* children[26];
};


// Node.h
//----------------
class Node : public Cell {
public:
Node() {}
int page;
void display();
Node* children[26];

Whatz this. Why do you need to have an array of 'Cell' pointers ( as
in the base class) and again 26 pointers again here. I guess thatz
against polymorphism as such.

Also the classes storing the data and modelling ought to be separate
( decoupled , to get the right term from the literature , that is).

That means, There might be a hierarchy of data classes, exhitinhg
polymorphism, but there ought to be a single class (that would have 26
pointers) that would be used an user to create the tree etc.

HTH

Karthik
 
M

Mika Vainio

hi john,
i just tried your idea but the last letter is still a cell. this is what i
wrote:

void Trie::insert(char *word, int page)
{
int iword = ((int)word[0])-97;

root->children[iword] = insert_one(word, page);
}

Cell* Trie::insert_one(char *word, int page)
{
Cell* new_cell = 0;

if (((int)word[1])-97 < 0) { // Node anlegen
new_cell = new Node();
cout << typeid(new_cell).name() << endl;
new_cell->display();
}
else
new_cell = new Cell;

for (int i = 0; i<26; i++)
new_cell->children = NULL;

new_cell->letter = word[0];

int iword = ((int)word[1])-97;
if (iword >= 0) {
new_cell->children[iword] = insert_one(word+1, page);
}

return new_cell;
}

output: class Cell *

best regards,
mika
 
M

Mika Vainio

ops, you're right - this comes from an earlier version where i used node for
all letters. i killed this line but that didn't change anything - the last
letter is still a cell...
and did i understand you correctly: the pointer vector should be changed
into 26 single cell pointers in a separate class?
best regards,
mika


Karthik said:
Mika said:
hi karthik,
yes, i have my own display() implementation (cout << "Pagenr: " <<
new_cell->page << endl;). and here are all my header files.
best regards,
mika

// Cell.h
//-----------------
class Cell {
public:
Cell() {}
virtual ~Cell();
virtual void display() const;

char letter;
Cell* children[26];
};


// Node.h
//----------------
class Node : public Cell {
public:
Node() {}
int page;
void display();
Node* children[26];

Whatz this. Why do you need to have an array of 'Cell' pointers ( as
in the base class) and again 26 pointers again here. I guess thatz
against polymorphism as such.

Also the classes storing the data and modelling ought to be separate
( decoupled , to get the right term from the literature , that is).

That means, There might be a hierarchy of data classes, exhitinhg
polymorphism, but there ought to be a single class (that would have 26
pointers) that would be used an user to create the tree etc.

HTH

Karthik
 
J

John Harrison

Mika Vainio said:
hi john,
i just tried your idea but the last letter is still a cell. this is what i
wrote:

I think I'm going to have to see a complete compilable program to help with
this one.

john
 
I

Iulian Dragos

Mika said:
Cell* Trie::insert_one(char *word, int page)
{
Cell* new_cell = 0;

if (((int)word[1])-97 < 0) { // Node anlegen
new_cell = new Node();
cout << typeid(new_cell).name() << endl;

Here use "cout << typeid(*new_cell).name() << endl; instead of
typeid(new_cell). Whithout dereferencing the pointer, you get the type
of the *pointer*, which is correct (Cell*).
new_cell->display();

which display() method is called? the one in Cell, or the one in Node. I
prefer printing a text in the derived method than using typeid...

hth,
Iuli
 
U

Uwe Schnitker

// Cell.h
//-----------------
class Cell {
public:
Cell() {}
virtual ~Cell();
virtual void display() const;

Look at this declaration of display,
char letter;
Cell* children[26];
};


// Node.h
//----------------
class Node : public Cell {
public:
Node() {}
int page;
void display();

and compare with this one, please.
Node* children[26];
};

You will see that the virtual function in the base class is a const one,
but the function declared in the derived class is not. Since this is C++,
not Java, the declaration in the derived class doesn't override that in the
base class, but rather hides it.

To take part in dynamic dispatch, the function in the derived class must have
exactly the same signature as the base class function. (Apart from the return
type, wich can be of a derived type if your compiler indeed supports "covariant
returns".)

HTH,

Uwe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top