From: hartman@ulogic.UUCP (Richard M. Hartman)
Newsgroups: comp.lang.c++
Subject: Re: static members in derived classes
Date: 15 Dec 92 21:47:19 GMT
Organization: negligable

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;
}