bernied@yoyodyne.ncsa.uiuc.edu (Bernhard Damberger) (06/02/91)
I 'am having some problems with virtual operators...maybe some one out there can help me. I have a class (called Base) that acts as a base class for all other classes. Base has all the relational operators defined (<, >, <=, etc.) as virtual. There is a subclass of Base (called TestInt) that overides the relational operators with its own (CFront even says TestInt's operators are hiding Base's operators). It looks something like this (some code deleted): class Base { ... public: virtual int operator< (Base &) const; // less than operator for Base virtual int operator> (Base &) const; // greater than operator ... // etc... }; class TestInt : public virtual Base { ... public: virtual int operator< (const TestInt &) const; // overide Base virtual int operator> (const TestInt &) const; // overide Base ... // overide the rest of Base's relational operators }; One of the things I want to do with a TestInt object (for instance) is insert it into a binary tree class. The binary tree class is defined as follows: class BinaryTree : public virtual Base { private: int num_nodes; // number of nodes in the BinaryTree BinaryTreeNode * root; // root of the tree public: ... virtual int insert (Base * object); ... }; BinaryTreeNode is a node in the tree that contains left and right pointers to new nodes. It also contains a pointer to a Base *. It looks like this: class BinaryTreeNode : public virtual Base { // public so BinaryTree can access members. Maybe make BinaryTree a friend? public: BinaryTreeNode *left; // pointer to the left Node BinaryTreeNode *right; // pointer to the right Node BinaryTreeNode *parent; // pointer to the parent Node Base *object; // the object this node contiains ... }; Notice BinaryTree takes in as its elements Base *. The problem occurs when I try and use BinaryTree::insert with an TestInt object. The code looks something like this: int BinaryTree::insert (Base * object) { BinaryTreeNode *parent = NULL; // parent of current node BinaryTreeNode *current = root; // current working node BinaryTreeNode *new_node = new BinaryTreeNode (object); if (new_node == NULL) return 0; // failed, return false // find place to insert object into BTree while (current != NULL) { parent = current; if (*object < *current->object) // <-problem is here!! current = current->left; else current = current->right; } // insert object into the BinaryTree new_node->parent = parent; if (parent == NULL) root = new_node; else if (*object < *parent->object) // <-problem is here!! parent->left = new_node; else parent->right = new_node; this->num_nodes++; // another node was added return 1; // return true } NOTE: The only elements I am inserting into the BinaryTree (at this point) are TestInt objects. The problem occurs when the "less than" operator is applied. I want CFront to call the most specific operator< as possible. In this case that would mean if I called BinaryTree::insert(foo), where foo is a TestInt pointer, I would want CFront to call TestInt::operator<(TestInt &) But, instead it calls the more basic Base::operator< (instead of TestInt::operator<). I have tried using the more "specific" notation, object->operator<(Base *), but I still get the same results. I also tried using pointers instead of references, but it still called Base::operator<. So how do I get CFront to use the virtual operators? When are the types bound (it looks like at compile time instead of run time)? How do I get CFront to call the most specific operator method? Any suggestions would be appreciated how to approach this problem. Thanks in advance. Bernhard Damberger bernied@yoyodyne.ncsa.uiuc.edu
sarima@tdatirv.UUCP (Stanley Friesen) (06/04/91)
I think this is getting to FAQ level. In article <1991Jun1.175904.20181@ux1.cso.uiuc.edu> bernied@yoyodyne.ncsa.uiuc.edu (Bernhard Damberger) writes: > > I 'am having some problems with virtual operators... >class Base { > ... >public: > virtual int operator< (Base &) const; // less than operator for Base > virtual int operator> (Base &) const; // greater than operator > ... // etc... >}; > >class TestInt : public virtual Base { > ... >public: > virtual int operator< (const TestInt &) const; // overide Base > virtual int operator> (const TestInt &) const; // overide Base > ... // overide the rest of Base's relational operators >}; OK, here's your problem. These do *not*, I repeat, *not*, override the "corresponding" virtual functions in Base! And why not? Because they do not have *exactly* *matching* signatures. By making the parameters 'const TestInt &' instead of 'Base &' you are *replacing*, not overriding, the functions in Base. Now, since the functions in Base have never been overridden, then a call through a Base pointer or reference will, naturally, use the pre-defined base functions. <<Irrelevant detail deleted>> > The problem occurs when the "less than" operator is applied. I >want CFront to call the most specific operator< as possible. In this >case that would mean if I called BinaryTree::insert(foo), where foo is >a TestInt pointer, I would want CFront to call TestInt::operator<(TestInt &) >But, instead it calls the more basic Base::operator< (instead of >TestInt::operator<). As indeed it should, given the above definitions. > So how do I get CFront to use the virtual operators? When are >the types bound (it looks like at compile time instead of run time)? >How do I get CFront to call the most specific operator method? This is quite simple, make the TestInt relational functions take parameters of type (Base &). Oh, you need 'const' parameters? Then you need to add the const qualified forms as virtual functions in the definition of class Base. -- --------------- uunet!tdatirv!sarima (Stanley Friesen)
mittle@blinn.watson.ibm.com (Josh Mittleman) (06/04/91)
In article <1991Jun1.175904.20181@ux1.cso.uiuc.edu>, bernied@yoyodyne.ncsa.uiuc.edu (Bernhard Damberger) writes: > > I 'am having some problems with virtual operators...maybe some > one out there can help me. I have a class (called Base) that acts as a base > class for all other classes. Base has all the relational operators defined > (<, >, <=, etc.) as virtual. There is a subclass of Base (called TestInt) that > overides the relational operators with its own (CFront even says TestInt's > operators are hiding Base's operators). It looks something like this (some > code deleted): Without reading any further, it is pretty clear what your problem is. Virtual functions must have identical signatures. Subclass::operator<(Subclass&) is not the same signature as BaseClass::operator<(BaseClass&), and the virtual function mechanism will not see a match. To get the virtual behavior, the Subclass function must have the signature Subclass::operator<(BaseClass&). When your compiler tells you that TestInt's operators are hiding Base's operators, that is a warning of a probable error. It means that TestInt's operators are not being treated as virtual functions. =========================================================================== Josh Mittleman (mittle@watson.ibm.com or joshua@paul.rutgers.edu) J2-C28 T.J. Watson Research Center, PO Box 704, Yorktown Heights, NY 10598