home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!olivea!spool.mu.edu!umn.edu!csus.edu!netcom.com!netcomsv!ulogic!hartman
- From: hartman@ulogic.UUCP (Richard M. Hartman)
- Newsgroups: comp.lang.c++
- Subject: Re: static members in derived classes
- Message-ID: <732@ulogic.UUCP>
- Date: 15 Dec 92 21:47:19 GMT
- References: <1g7c8fINNdhf@horus.ap.mchp.sni.de>
- Organization: negligable
- Lines: 139
-
- In article <1g7c8fINNdhf@horus.ap.mchp.sni.de> werner@diamant.uucp writes:
- >We have problems in initializing static class members in derived classes.
- >Look at the following example:
- >
- >#include <iostream.h>
- >
- >// base class
- >
- >class B
- >{
- >public:
- > B() {}
- > static int i;
- >};
- >int B::i = 27; // unique definition, works as expected
- >
- >// subclass
- >
- >
- >class S : public B
- >{
- >public:
- > S() {}
- > getX( void ) { return i; }
- >};
- >//int S::i = 55 ;
- >// error (AT&T): S::i not a member of S
- >// error (GNU g++): multiple initializations of static member B::i
- >
- >void main( void )
- >{
- > S s;
- > cout << s.getX() << "\n";
- > // One gets the value of the base class!!
- >}
- >
- >Stroustrop (p. 165) writes that static class members act similar to
- >global variables. In the above example we would expect that for the
- >subclass a new instace of the static variable is created which can be
- >initialized in analogy to the base class.
- >
- >But that seems to be not right. There exists only !!one!! instance of
- >the static member which is related to the base class !!and!! the
- >subclass.
- >
- >We don't understand this behavior of C++. Can anyone explain to us.
-
- I think the shortest answer is found in ARM, ss9.4 (p179 in my edition,
- but then I could not find any reference to "static" on p165 of my ARM,
- so I include the subsection number for your convenience):
-
- A static member is not part of objects of a class.
-
- I know that I have found this annoying in my own code development.
- I wanted a static socket member function that I could for an intertask
- message base class to be accessed by task-specific subclases such that
- all instances of, say, XXXMgrClass would be using the same socket
- to the XXXMgr task. All instances of YYYMgrClass would be using a
- different socket from the one used in XXXMgrClass.
-
- I found that I had to declare a new static for each derived class and
- then provide a virtual getIdent() member function that returned the
- value stored in the static for that subclass even if operating off
- a pointer to the base class.
-
- This worked something like the program appended to this message. Note
- that if you do note redefine the virtual getIdent() function for class
- B you will end up with the value '1' instead of '2' coming out. Try
- commenting the lines marked to see this.
-
- Actually I have no static member in the base class in my actual
- final message class. The getSocket() function is a true virtual
- being declared as "virtual Socket &getSocket() = 0;", leaving all
- implementation up to the base classes.
-
- Admittedly it would be VERY nice if there were a static that
- reinstantiated (I can't think of a better term for the effect...)
- itself with each derived subclass, but there are also uses for
- the current behavior, so the best solution would be to allow
- both types of behavior, selected somehow by the syntax, but what
- that would look like I couldn't imagine.....
-
- For now we just have to live with it. :-(
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- Blasting, bursting, billowing forth with |
- the power of ten billion butterfly sneezes, | -Richard Hartman
- Man, with his flaming fire, | hartman@uLogic.COM
- has conquered the wayword breezes. |
-
- #include <stdlib.h>
- #include <stream.h>
-
- class A
- {
- protected:
- static int i;
- public:
- A() {};
-
- virtual int getIdent();
- };
-
-
-
- class B : public A
- {
- protected:
- static int i;
- public:
- B() {}
- int getIdent(); // comment out to break function
- };
-
- class C : public A
- {
- public:
- C() {}
- int getIdent();
- };
-
- int A::i = 1;
- int A::getIdent() { return i; }
- int B::i = 2;
- int B::getIdent() { return i; } // comment out to break function
- int C::getIdent() { return i; }
-
- main()
- {
- A a;
- B b;
- C c;
-
- A *p1 = &a, *p2 = &b, *p3 = &c;
-
- cout << a.getIdent() << b.getIdent() << c.getIdent() << endl;
- cout << p1->getIdent() << p2->getIdent() << p3->getIdent() << endl;
- }
-