whisd@sersun1.essex.ac.uk (Whiteside S D B) (04/30/91)
I noticed something in some classes I was producing using Borland C++ recently. It seems anomalous, can anyone let me know of what they think: I had a base class in which I declared a static data member. I then derived TWO separate classes which both inherited from the base class. Then these classes were instanstiated as objects I found that for BOTH the static data member (a pointer) had the SAME value. Now I know that a static member is the same for every object of a class, but is the same for every object of a DERIVED class? My two objects were not of class "base" but of classes "derived1" and "derived2" respectively. I expected each object of Derived1 to have the same data member inherited from base class, and likewise for Derived2, but not that all objects of BOTH classes would have the same. I've searched literature high and low for an answer to this. Nowhere do they mention what happens when you inherit a static member (data or function). Any suggestions or corrections welcome. Simon Whiteside
landauer@morocco.Eng.Sun.COM (@morocco.eng [Doug Landauer]) (05/01/91)
> Now I know that a static member is the same for every object of a class, > but is the same for every object of a DERIVED class? My two objects were > not of class "base" but of classes "derived1" and "derived2" respectively. The whole point of inheritance (public inheritance, at least) is that the derived "is a" base, so that you can use the derived object as if it were a base object. The static member is shared among all instances (objects) of the base class, including the embedded "base" object that lives inside each derived object. > I've searched literature high and low for an answer to this. Nowhere do > they mention what happens when you inherit a static member (data or > function). Yeah, I think you're right -- I can't find a particularly explicit mention either of this particular issue (inheritance vs static members), or of the general principle that a derived "is a" base. Perhaps X3J16's editor could add a sentence or two to make these things more clear. Here's the things I found that came closest to these issues: E&S, Section 9.4: There is only one copy of a static data member, shared by all objects of the class in a program. E&S, Section 10: A derived class can itself serve as a base class ... E&S, Section 11.2: Specifying a base class "private" does not affect access to static members of the base class. (Note that the latter has been rewritten a bit in the current draft -- it says something more like Because of the rules on pointer conversion (section 4.6), a static member of a private base class may be inaccessible as an inherited name, but accessible directly. now. But remember that it's still just a Draft.) -- Doug Landauer - Sun Microsystems, Inc. - Languages - landauer@eng.sun.com
philip@pescadero.stanford.edu (Philip Machanick) (05/01/91)
In article <5069@servax0.essex.ac.uk> whisd@sersun1.essex.ac.uk (Whiteside S D B) writes: >I noticed something in some classes I was producing using Borland C++ recently. > >It seems anomalous, can anyone let me know of what they think: > >I had a base class in which I declared a static data member. > >I then derived TWO separate classes which both inherited from the base class. > >Then these classes were instanstiated as objects I found that for BOTH the static data member (a pointer) had the SAME value. > >Now I know that a static member is the same for every object of a class, but is the same for every object of a DERIVED class? [...] >I've searched literature high and low for an answer to this. Nowhere do they mention what happens when you inherit a static member (data or function). > I had exactly the the same problem with AT&T cfront 2.0 last year. On a quick scan of ARM, I could find no mention of this behaviour, but lots of people assured me that this is "standard". Philip Machanick
mr3@ukc.ac.uk (M.Rizzo) (05/06/91)
In article <5069@servax0.essex.ac.uk> whisd@essex.ac.uk (Whiteside S D B) writes: >I had a base class in which I declared a static data member. > >I then derived TWO separate classes which both inherited from the base class. > >Then these classes were instanstiated as objects I found that for BOTH the static data member (a pointer) had the SAME value. > >Now I know that a static member is the same for every object of a class, but is the same for every object of a DERIVED class? > >My two objects were not of class "base" but of classes "derived1" and "derived2" respectively. > >I expected each object of Derived1 to have the same data member inherited from base class, and likewise for Derived2, but not that all objects of BOTH classes would have the same. > >I've searched literature high and low for an answer to this. Nowhere do they mention what happens when you inherit a static member (data or function). > >Any suggestions or corrections welcome. I've experienced this problem before. The only solution I found was to re-declare the static data members in every subclass I needed them. However this should be done with care. If a base class member function refers to a static data member, then if this function is inherited by a derived class re-declaring the same static member, the base class static member will still be the one referenced by the inherited function. What we need here is virtual static data members ! Unfortunately there are no such thingies :-( To solve this problem you can define two virtual non-static functions to read and write the member - though again this must be done for every derived class where the static member is declared. Macros are very handy here ! Does anybody know of another (possibly better) approach ? Also, a suggestion - why not consider adding virtual static data members to the language defintion ? (No I haven't got it wrong - I know ``virtual'' is normally associated with functions) I think they could be useful as described in the above case. The need to have derived classes with _their own_ static data often arises e.g. to store an instance count. >Simon Whiteside Michael Rizzo
philip@pescadero.stanford.edu (Philip Machanick) (05/06/91)
In article <7510@harrier.ukc.ac.uk> mr3@ukc.ac.uk (M.Rizzo) writes: >In article <5069@servax0.essex.ac.uk> whisd@essex.ac.uk (Whiteside S D B) writes: > >>I had a base class in which I declared a static data member. >> >>I then derived TWO separate classes which both inherited from the base class. >> >>Then these classes were instanstiated as objects I found that for BOTH the static data member (a pointer) had the SAME value. [...] >The only solution I found was to re-declare the static data members >in every subclass I needed them. However this should be done with >care. If a base class member function refers to a static data member, >then if this function is inherited by a derived class re-declaring the >same static member, the base class static member will still be the one >referenced by the inherited function. > >What we need here is virtual static data members ! Unfortunately there >are no such thingies :-( > >To solve this problem you can define two virtual non-static functions >to read and write the member - though again this must be done for >every derived class where the static member is declared. Macros are very >handy here ! > >Does anybody know of another (possibly better) approach ? [...] Make the statics private (rather than protected). Then you are forced to redeclare them for derived classes. This still doesn't help you if you call a function higher up the hierarchy - the only solution I can propose here is that you pass the statics as parameters at all times. This, combined with the use of private, ensures you get the right one. Again - a better approach would be appreciated. Philip Machanick
daves@ex.heurikon.com (Dave Scidmore) (05/08/91)
whisd@essex.ac.uk (Whiteside S D B) writes: >I had a base class in which I declared a static data member. >I then derived TWO separate classes which both inherited from the base class. >Then these classes were instanstiated as objects I found that for BOTH the >static data member (a pointer) had the SAME value. philip@pescadero.stanford.edu (Philip Machanick) writes: >Make the statics private (rather than protected). Then you are forced to >redeclare them for derived classes. This still doesn't help you if you call a >function higher up the hierarchy - the only solution I can propose here is that >you pass the statics as parameters at all times. This, combined with the use of >private, ensures you get the right one. Perhaps I am dense, but I would assume that if a static member variable was declared in a base class it is because you want only one instance of that variable to exist for that class and all those derived from it. I am having trouble envisioning a situation where you would want multiple static member variable (a contradiction in terms IMHO). It seems to me that if you want separate static member variables in derived classes you would declare them there. This problem seems somewhat analogous to the case where you want all objects of a class to be "attached" to some set of possible static variables though not all to the same variable. For example I have created an error handler classes to deal with all the different types of errors one particular program can have. In the case of internal errors the program may exit immediately. So do file I/O errors, but they always print a file I/O location. Up to 'n' compilation errors can occur before exiting, and some error messages are just warnings and do not exit at all. The solution was to create groups or classes of error handlers and attach each error handler to the appropriate class of error handler. This is done by requiring a pointer to the error handler class class when constructing an error handler. Would it be practical in your situation to force construction of each base class to include a pointer to a static member variable which it uses in place of a permanent static member variable. Classes derived from the base class can then provide their own static member variable and construct the base class using that variable. Just a thought. If having the base class store a pointer to a "static" variable represents too much overhead then perhaps requiring base class method invoctions to provide a pointer to the derived class static member variable would work. -- Dave Scidmore, Heurikon Corp. dave.scidmore@heurikon.com
noren@dinl.uucp (Charles Noren) (05/10/91)
In article <520@heurikon.heurikon.com> daves@ex.heurikon.com (Dave Scidmore) writes: > >Perhaps I am dense, but I would assume that if a static member variable >was declared in a base class it is because you want only one instance of >that variable to exist for that class and all those derived from it. I >am having trouble envisioning a situation where you would want multiple >static member variable (a contradiction in terms IMHO). There are cases where you may want multiple instances of static members of the same name. One example of use is in the NIH Class Library (NIHCL). A good description of its use is found in the book DATA ABSTRACTION AND OBJECT- ORIENTED PROGRAMMING IN C++, by Gorlen, Orlow, Plexico (1990, John Wiley & Sons, ISBN 0-471-92346-X), pp 144-146. In NIHCL, the static member classDesc is defined for each class, and you must define it for each class you derive from another NIHCL class (this is done for you in their DECLARE_MEMBERS and DEFINE_CLASS macros). The classDesc member is an instance of NIHCL's Class class which keeps certain information specific to the class it is defined in. Its address is also used to identify what class an object belongs to. For instance, every class implements the member function isA usually as: const Class* X::isA() const {return &classDesc;} Again, this is provided for the NIHCL applications user inside the macro DEFINE_CLASS. Certainly there are other ways of providing class identification, but this gives a flavor of what can be done by "overloading" a static member with another of the same name. BTW, using this mechanism inside NIHCL's castdown functions also provides a safe mechanism for doing "down casting" of object pointer from classes with virtual base objects (described on pp. 325-328 of DATA ABSTRACTION). -- Chuck Noren NET: dinl!noren@ncar.ucar.edu US-MAIL: Martin Marietta I&CS, MS XL8058, P.O. Box 1260, Denver, CO 80201-1260 Phone: (303) 977-1646