Problem with pointers (inherited classes)

Hello again.

In my project, AnyObject is the basic class containing a destructor and a constructor only, and Lex is an inherited class, which includes a public char symbol Lex::cont and a method for displaying it:

class Lex: public AnyObject
{
public:
char cont;
Lex(char cn){ cont=cn; };
void show() { cout << cont; };
~Lex() { };
};


I need to display a char element which is recognized as AnyObject in the code by modifying the pointer type. So it looks like:


Lex *lx;
AnyObject *ref;
ref = new AnyObject; //initializing a pointer to AnyObject
ref=&(btree::root->d); //btree::root->d is declared as AnyObject
lx = (Lex*)(ref);
(*lx).show();


The compiler accepts it, but displays totally different characters. The program itself is OK, because without these classes it worked just fine. Where can I be wrong?

Thank you!
What you have there will fail primarily because no Lex object exists. The cast on (what would be) line 5 (if you had used code tags) will fail at runtime.

The call to show() will produce an "undefined result". What are you getting?

What you have is odd and incomplete in terms of class structure.
To use polymorphism, there must be a show method in the base class too.

If you add this to your AnyObject class:
virtual void show() { cout << "default object" << endl; }
Then you could do the following in main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    AnyObject A;
    Lex L('L');

    AnyObject *pAny = NULL;

    pAny = &A;
    pAny->show();// should produce "default object"

    pAny = &L;
    (*pAny).show();// should produce "L"

    return 0;
}

Is this what you are trying to do?
Note the two ways I called the show() function. They are equivalent.
Last edited on
Thank you for the explanation. My problem is that I don't have what you show as 'L'. The Lex character is an element of a binary tree of AnyObject-s. So I need a way to display it if it's taken for granted that it is a Lex object indeed.
OK. I see your other thread. btree::root->d is a character, so what you are trying to do here is nonsense. Good luck.
OK, it still produces "default object". :(

Perhaps the way I assigned btree::root->d can shed some light on the problem? Here's a simplified scheme:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
btree make_tree (btree a, btree b, Lex c) //formerly was AnyObject c
// procedure creating a binary tree by knowing the two branches and the root element (later referred to as btree::root->d)
{
   btree p;
   p.root = new node;
  (p.root)->d=c; //assigning root value to the new tree
  (p.root)->ls=a.root; //left branch is a known tree
  (p.root)->rs=b.root; //right branch is another known three
  return p;    
}

Then:
Lex a1('L'); //it isn't actually L, but some char object
bt= make_tree (<some known tree>, <some known tree>, a1);


So in the procedure generating a tree it is an AnyObject, but in its argument it's a Lex. What else must be done for it to recognize it as Lex?

Edit: changing the parameter to btree make_tree (btree a, btree b, Lex c) doesn't help, perhaps because the tree still consists of AnyObjects.

Regarding the other thread: it is a character in a different version of the program, here I reset it to make a more general program.
Last edited on
OK. I see that the case in your other thread should not be considered here.

Sorry I assumed otherwise.

If btree::root->d is an AnyObject then a call to show() will produce "default object" every time.

If btree::root->d is a Lex object then a call to show() will produce whatever it's supposed to produce every time.

If it keeps giving you "default object" it's because you keep calling show() with a pointer pointing to an AnyObject, not a Lex object.
Last edited on
Thanks. Above, I described how the value is assigned. That is, first I create a tree of AnyObject-s whose top value is actually a Lex object. Then I use what you said, call it using
1
2
3
4
    
AnyObject *pAny = NULL;
pAny = &(btree::root->d);
pAny->show();


Could you please look at the fragment above to see where the fault can be? Sorry if it bothers you, I just need someone to explain it to me.
Hmmm. On line 14 above
bt= make_tree (<some known tree>, <some known tree>, a1);
some variable name bt is assigned a copy of a local instance of a btree. Perhaps bt is an already allocated btree object? You won't get a new btree out of your a call to the make_tree() function.

How are bt and btree::root->d related???
Is root a static member of the btree class? is there a btree namespace?
What exactly is btree::root ??

I think we are only going to continue in circles here.
Where is btree::root->d coming from?
Last edited on
Well, I tried applying
1
2
3
AnyObject *pAny = NULL;
pAny = &(...);
pAny->show();


in different places of the code to see when Lex becomes AnyObject, and it seems I found the catch. If it doesn't help, I'll answer your questions in a greater detail.

(make_tree is a function creating a new binary tree out with two existing binary trees as branches and a given AnyObject as the root element; bt is a subsidiary btree variable; btree::root->d is the root value if it's still important. btree::root is a pointer to the root element (node* root), an element itself is defined as
1
2
3
4
5
6
struct node
{
  AnyObject d;
  node *ls;
  node *rs;
};

)

OK. In the function make_tree there is a problematic assignment

rt->d=c;

rt is a *node element, so rt->d is an AnyObject, whereas c is a Lex object. After this,
1
2
3
AnyObject *pAny = NULL;
pAny = &(btree::root->d);
pAny->show();

produces the default string.

Is there any way I can redefine rt->d so it would still have AnyObject type, but could return the character contained in Lex when address with pAny->show()? As far as I understand, this assignment just doesn't work, but I don't know any alternative...

If you need more information about the meaning of any variables or procedures, the code is totally mine so I always can answer.
Last edited on
Your problems may stem from the fact that your make_tree() does not create a new tree.

It would have to be like this:
1
2
3
4
5
6
7
8
9
10
11
// return a pointer to the dynamically allocated object or it will be lost
btree* make_tree (btree a, btree b, Lex c) 
{
   btree* p = new btree(.....);
    p->root = new node;
  
  p->root->d=c; //assigning root value to the new tree
  p->root->ls=a.root; //left branch is a known tree
  p->root->rs=b.root; //right branch is another known three
  return p;    
}

That function returns a pointer to the new tree.
It's also a bad idea to pass objects by value when the object has dynamically allocated members. Are you aware of the hazards in doing so?
Pass by const& instead. Does a Lex object have dynamically allocated members too?
Thank you, but in fact make_tree works, because:
1) it worked when I used char instead of AnyObject;
2) it works fine now as I test the program, just displays the default string instead of characters. Everything else is exactly as it should be.

To be honest, I'm a student and there's much I don't know, so I use this individual task to expand my programming skills. :) For the time being, I just would like to make the program do what I need, and I'll gladly modify and optimize it later. No, Lex is described as follows:

1
2
3
4
5
6
7
8
class Lex: public AnyObject 
{
  public:  
  char cont;       
  Lex(char cn){ cont=cn; };   
  virtual void show() { cout << cont; };  
  ~Lex() { };
  };


The problem seems to be pinpointed: in my original make_tree procedure I use the assignment (p.root)->d=c, where c is of Lex type and (p.root)->d, which soon becomes btree::root->d, is an AnyObject. I understand that only pointers can preserve the Lex::cont value with such a transition. Could you help me eliminate exactly this issue by modifying the procedure? Thanks again!

Don't think that I ignore your advice, I only want to see the program work. I'll fix the remaining issues later.
No worries. It's just that some of the problems I see could easily be causing lots of problems (passing btrees by value being especially bad).

Your make_tree() function does not create a new tree.
In this assignment:bt= make_tree (<some known tree>, <some known tree>, a1);
That is the local variable p being copied by value to the object bt. bt would have to be an existing btree object (where does bt come from?) and operator= would have to be overloaded to copy that correctly.

EDIT: I didn't see what ne555 and cire did below. Sorry
Last edited on
@OP: object slicing.
1
2
3
4
5
6
struct node
{
  AnyObject d;
  node *ls;
  node *rs;
};


To expound a little on what ne555 said, d can never be anything but an "AnyObject". Assigning it the value of a derived object will result in the derived object being sliced down to it's AnyObject subobject when it is stored in D.

So, the reason you're not getting polymorphic behavior is because you're only dealing with one type.
Topic archived. No new replies allowed.