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