[gnu.g++.help] initialization of objects within a library

engeln@danetis.UUCP (Werner Engeln) (11/22/90)

To ensure that global objects of a library is initialized befor its first
use, I implemented a counter to maintain the number of translation units
using it (see "the annotated C++ reference manual section 3.4, Ellis &
Stroustrup).[example below]
To my confusion, my library objects are constructed (and destructed) twice !
How can I reduce constructor calls to only ONE for each global object ??

mail, and I will post a summary

engeln@danetis.uucp
------------------------------- cut here -- nifty_library.h -----------
// nifty_library.h
#ifndef nifty_h
#define nifty_h

class foo {
public :
	foo (const char *);
	~foo ();
	void print ();
private :
	const char * name;
};

class nifty_counter {
public :
	nifty_counter ();
	~nifty_counter ();
private :
	static count;
};

#ifndef nifty_cc
// global objects
extern foo aFoo;

// counter of translation units
static nifty_counter nifty;

#endif nifty_cc
#endif nifty_h
------------------------------- cut here -- nifty_library.cc ----------
#define nifty_cc
extern "C" void printf (const char *, ...);

// declare global objects to resolve external references
foo aFoo ("aFoo by library startup");

// memberfunctions
foo::foo (const char * c)
: name (c)
{
	printf ("constructing %s\n", name);
}

foo::~foo ()
{
	printf ("destructing %s\n", name);
}

void foo::print ()
{
	printf ("foo named %s\n", name);
}

// counter implementation
nifty_counter::nifty_counter ()
{
	if (count++ == 0) {
		// initialize global objects
		aFoo.foo ("aFoo by nifty_counter");
	}
}

nifty_counter::~nifty_counter ()
{
	if (--count == 0) {
		// clean up global objects
		aFoo.foo::~foo ();
	}
}
------------------------------- cut here -- nifty_user.cc -------------
#include "nifty.h"

void main ()
{
	aFoo.print ();
}
------------------------------- cut here -- output --------------------
constructing aFoo by nifty_counter
constructing aFoo by library startup
foo named aFoo by library startup
destructing aFoo by library startup
destructing aFoo by library startup
--
Werner Engeln                Phone: +49-711/736051  FAX: +49-711/736054
Danet-IS GmbH                UUCP:   engeln@danetis.uucp
Waldburgstrasse 17 - 19      BITNET: engeln%danetis.uucp@unido.bitnet
D-7000 Stuttgart 80          X.400:  C=DE;A=DBP;P=DANET;O=IS;S=Engeln

rmartin@clear.com (Bob Martin) (11/28/90)

I am posting this because your mail bounced...

In article <3306@danetis.UUCP> you write:
>To ensure that global objects of a library is initialized befor its first
>use, I implemented a counter to maintain the number of translation units
>using it (see "the annotated C++ reference manual section 3.4, Ellis &
>Stroustrup).[example below]
>To my confusion, my library objects are constructed (and destructed) twice !
>How can I reduce constructor calls to only ONE for each global object ??
>
>mail, and I will post a summary
>
>engeln@danetis.uucp
>------------------------------- cut here -- nifty_library.h -----------
>..... junk taken out .....
>
>// counter of translation units
>static nifty_counter nifty;

^^^^^^^^^^^^^^^^^^^^^^^^^^^^  This constructs nifty.  The constructor
							  for nifty explicity calls the constructor
							  for foo.  That is the cause of the first
							  aFoo construction by nifty.
>
>#endif nifty_cc
>#endif nifty_h
>------------------------------- cut here -- nifty_library.cc ----------
.....  Junk taken out.
// declare global objects to resolve external references
foo aFoo ("aFoo by library startup");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	This causes aFoo to be constructed and so the foo::foo constructor
	is called.  This is the cause of the second construction by
	library startup.

.....  Junk taken out.
>
>// counter implementation
>nifty_counter::nifty_counter ()
>{
>	if (count++ == 0) {
>		// initialize global objects
>		aFoo.foo ("aFoo by nifty_counter");
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
		Ouch!  This makes an explicit call to the contstructor for
		foo.  You should never explicity call a constructor.  It is
		the compiler's job to call constructors.  This will certainly
		cause trouble for you.
>	}
>}
>

You should never ever call a constructor or destructor yourself.  The
compiler will do these things for you...

Let me recommend that you declare the variable "aFoo" as follows:

	foo *aFoo;    <--- as a pointer to a foo.

Now in nifty_counter::nifty_counter() you can create a foo as follows:

	if (count++ == 0)
	{
		aFoo = new foo("aFoo by nifty_counter"); 
			// will call foo::foo for you.
	}

Then in nifty_counter::~nifty_counter() you can destroy the foo
as follows:

	if (--count == 0)
	{
		delete aFoo; // will call foo:~foo for you.
	}

Hope this helps.

-- 
+-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for |
| rmartin@clear.com    |:R::R:C::::M:M:M:M:| my words but me.  I want  |
| uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all   |
+----------------------+:R::R::CCC:M:::::M:| the blame.  So there.     |

engeln@danetis.UUCP (Werner Engeln) (12/06/90)

rmartin@clear.com (Bob Martin) writes:

>You should never ever call a constructor or destructor yourself.  The
>compiler will do these things for you...

>Let me recommend that you declare the variable "aFoo" as follows:

>	foo *aFoo;    <--- as a pointer to a foo.

>.....  Junk taken out.

>Hope this helps.

This is no general solution.
sometimes I have no pointers but REAL objects (like cin & cout in the
AT&T istream & ostream library)

>In article <3306@danetis.UUCP> you write:
>>To ensure that global objects of a library is initialized befor its first
>>use, I implemented a counter to maintain the number of translation units
>>using it (see "the annotated C++ reference manual section 3.4, Ellis &
>>Stroustrup).[example below]

I only have this reference and don't know their mystic tricks to initialize
cin and cout by use of a nifty_counter.
Is Stroustrup telling lies, or is there any hidden C++ feature ??


-- 
Werner Engeln                Phone: +49-711/736051  FAX: +49-711/736054
Danet-IS GmbH                UUCP:   engeln@danetis.uucp
Waldburgstrasse 17 - 19      BITNET: engeln%danetis.uucp@unido.bitnet
D-7000 Stuttgart 80          X.400:  C=DE;A=DBP;P=DANET;O=IS;S=Engeln