mcardle@prl.philips.nl (Owen McArdle) (03/08/91)
[Apologies for those of you who are reading this twice, I've broadened the distbn. to world, hoping for some more reaction] Ok folks, I've been banging my head against this one for too long now, and getting nowhere. I figure at this stage that either I'm missing some really obvious coding error, or I really have a problem with C++/NIH. To draw on your collective wisdom would seem the best way forward, so here goes. First the base: NIH 3.0 HP/Apollo DN[34]000, running sr10.2/10.3 CC = Domain/C++ V2.1.0;CC (C++), revision 1.0, 11/05/90 cc = Domain/C Version 6.8 Now the problem: I was trying to make use of Multiple Inheritance, and found myself with the need to make use of a few virtual base classes "in series", Eg: A -deriv-> B -v_deriv-> C -v_deriv-> D ignoring all other derived classes. Creating an instance of D is OK, but certain actions using it are not. I include a stripped version of the C++ code below: ///////////////////////////////////////////////////////////////////// #include "Object.h" #include "String.h" #include "Set.h" #include "nihclconfig.h" #ifndef MI #define MI #endif class Node : public String { DECLARE_MEMBERS(Node); int soon, late; protected: virtual void storer(OIOofd&) const {} virtual void storer(OIOout&) const {} public: Node(); Node(const String&, int ni, int no); virtual void printOn(ostream& strm =cout) const; }; #define THIS Node #define BASE String #define BASE_CLASSES BASE::desc() #define MEMBER_CLASSES #define VIRTUAL_BASE_CLASSES DEFINE_CLASS(Node, 0, "Node.cxx", NULL, NULL); Node::Node() { late = soon = -2; cerr << "In Node::Node()\n"; } Node::Node(const String& name, int ni, int no) : String(name) { late = ni; soon = no; cerr << "In Node::Node(s,i,o)\n"; } void Node::printOn(ostream& strm) const { strm << " Node \nSoon =\t" << soon << "\tLate =\t" << late << endl; } Node::Node(OIOifd& fd) : Object(fd), String(fd) {} Node::Node(OIOin& strm) : Object(strm), String(strm) {} ///////////////////////////////////////////////////////////////////// class PrimNode : public VIRTUAL Node { DECLARE_MEMBERS(PrimNode); protected: virtual void storer(OIOofd&) const {} virtual void storer(OIOout&) const {} public: PrimNode(); PrimNode(const String& name, int ni = 2, int no = 1); virtual void printOn(ostream& strm =cout) const; }; #undef THIS #define THIS PrimNode #undef BASE #define BASE Node #undef BASE_CLASSES #define BASE_CLASSES BASE::desc() #undef MEMBER_CLASSES #define MEMBER_CLASSES #undef VIRTUAL_BASE_CLASSES #define VIRTUAL_BASE_CLASSES BASE::desc() DEFINE_CLASS(PrimNode, 1, "PrimNode.cxx", NULL, NULL); PrimNode::PrimNode() { cerr << "In PrimNode::PrimNode()\n" << endl; } PrimNode::PrimNode(const String& name, int ni, int no) : Node(name,ni,no) { cerr << "In PrimNode::PrimNode(s,i,o)\n"; } void PrimNode::printOn(ostream& strm) const { strm << " Prim "; Node::printOn(strm); } PrimNode::PrimNode(OIOifd& fd) : Object(fd), Node(fd) {} PrimNode::PrimNode(OIOin& strm) : Object(strm), Node(strm) {} ///////////////////////////////////////////////////////////////////// class AssignNode : public VIRTUAL PrimNode { DECLARE_MEMBERS(AssignNode); protected: virtual void storer(OIOofd&) const {} virtual void storer(OIOout&) const {} public: AssignNode(const String& name, int ni = 1, int no = 1); virtual void printOn(ostream& strm =cout) const; }; #undef THIS #define THIS AssignNode #undef BASE #define BASE PrimNode #undef BASE_CLASSES #define BASE_CLASSES BASE::desc() #undef MEMBER_CLASSES #define MEMBER_CLASSES #undef VIRTUAL_BASE_CLASSES #define VIRTUAL_BASE_CLASSES BASE::desc() DEFINE_CLASS(AssignNode, 0, "AssignNode.cxx", NULL, NULL); AssignNode::AssignNode(const String& name, int ni, int no) : Node(name,ni,no), PrimNode(name,ni,no) { cerr << "In AssignNode::AssignNode(s,i,o)\n"; } void AssignNode::printOn(ostream& strm) const { strm << " Assign "; Node::printOn(strm); } AssignNode::AssignNode(OIOifd& fd) : Object(fd), Node(fd), PrimNode(fd) {} AssignNode::AssignNode(OIOin& strm) : Object(strm), Node(strm),PrimNode(strm) {} ///////////////////////////////////////////////////////////////////// main() { Set nTable; AssignNode *an = new AssignNode("ASGN"); cout << "Hash result: " << an->hash() << endl; cout << "Hash result: " << String::castdown((Object*)an)->hash() << endl; nTable.add(*an); cout << nTable; } ///////////////////////////////////////////////////////////////////// running this program gets me: In Node::Node(s,i,o) In PrimNode::PrimNode(s,i,o) In AssignNode::AssignNode(s,i,o) Hash result: 1095976778 Hash result: 1095976778 Memory fault with traceback: #> tb Process 26728 (parent 26375, group 26728) Time 91/03/06.11:34(NED) Program /local_user/mcardle/src/cxx/test/EXPM2 Status 00040004: reference to illegal address (OS/MST manager) In routine "String::hash" line 544 Called from "Set::findIndexOf" line 103 Called from "Set::add" line 137 Called from "main" line 142 Called from "unix_$main" line 114 Called from "_start" line 132 Called from "PM_$CALL" line 176 Called from "pgm_$load_run" line 903 Called from "pgm_$invoke_uid_pn" line 1124 ///////////////////////////////////////////////////////////////////// Stepping into the routine Set::add, up to String::hash, I can see that the values of the String variables (len, p) are completely wrong. Why I haven't worked out yet. Any ideas ? Does it seem to work for you ? I have tried a similar structure using just C++ constructs, and it works OK, but like I say I may just be blindly missing something here. All suggestions gratefully accepted, Replies by e-mail please, should something of general interest result I'll post again. Is mise le meas Owen P.McArdle || e-mail : mcardle@prl.philips.nl Philips Research Labs. || 'phone : +31-40-742824 Eindhoven || quote : "Oh no, not again" The Netherlands || vice : GS450L