Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Global objects...

Reply
Thread Tools

Global objects...

 
 
Phlip
Guest
Posts: n/a
 
      09-19-2007
barcaroller wrote:

> What is the proper way to instantiate a global object that is visible to
> all
> modules in a project?


Look up the "singleton pattern" for C++.

If you write this...

Global aGlobal;

....then code in other "modules" (translation units) that evaluates before
main() might access aGlobal. C++ cannot guarantee the order of
initialization of global objects.

The fix is this:

Global &getGlobal()
{
static Global aGlobal;
return aGlobal;
}

A static at function scope is guaranteed to initialize before its first use.

> Currently, I instantiate the object in one module
> and then use 'extern' in a header file which is "included" in all modules,
> but I wonder whether this is the best way.


That's the unsafe way, but it's only unsafe if you write clever clever code,
such as other global constructors, that call before main().

Next, you should not treat this object as a global, even if it lives longer
than main(). All your methods should not just reach out and grab it; that
makes your code hard to upgrade, hard to decouple from this object, and
hard to unit test. Your top-level methods should pass values from this
global into their called methods, and these should only rely on the passed
values.

--
Phlip
http://www.oreilly.com/catalog/9780596510657/
^ assert_xpath
 
Reply With Quote
 
 
 
 
barcaroller
Guest
Posts: n/a
 
      09-19-2007
What is the proper way to instantiate a global object that is visible to all
modules in a project? Currently, I instantiate the object in one module and
then use 'extern' in a header file which is "included" in all modules, but I
wonder whether this is the best way.


 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      09-19-2007
* barcaroller:
> What is the proper way to instantiate a global object that is visible to all
> modules in a project? Currently, I instantiate the object in one module and
> then use 'extern' in a header file which is "included" in all modules, but I
> wonder whether this is the best way.


Read the FAQ on global initialization order fiasco, and Google for
Meyer's singleton.

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
werasm
Guest
Posts: n/a
 
      09-20-2007

Phlip wrote:

> Your top-level methods should pass values from this
> global into their called methods, and these should only rely on the passed
> values.


Yes, Phlip (generally value your thoughts, BTW). That was always the
way I've
done it, usually using either constructor parameters or methods like
<associate>
or <adopt>, depending on circumstance... But I've found that I write a
lot of
code that has just that purpose. Also note that Singleton is not good
enough,
as Singleton binds you to implementation (most often), except if the
Singleton's
implementation hides behind a pimpl, but that does not necessarily
allow
polymorphism, although I suppose you could get polymorphism by using
the
bridge pattern - having concrete relationships, these making use of
factories
to achieve what is required. Hmmm, Singletons that make use of
factories to
achieve polymorphism. I suppose that is a solution, yes. OTOH
factories
tend to get sooo complex...

I suppose you could make more valuable contributions (any other
ideas?).
Another idea that struck me was the idea of a Singleton interface, but
no
one seemed to like the idea. I suppose it is too intrusive. It boils
down to this:

#include <cassert>
#include <boost/noncopyable.hpp>

class SingleIFBase : boost::noncopyable
{
protected:
enum eAction{ eCreate, eDestroy, eGet };
};

template <class T>
class SingleIF : SingleIFBase
{
public:
static T& get();

protected:
SingleIF( T& impl );
~SingleIF();

private:
static T* doAction( eAction, T* impl = 0 );
};

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
template <class T>
T* SingleIF<T>::doAction( eAction action, T* impl )
{
static SingleIF* inst( 0 );
if( action == eGet )
{
assert( inst );
}
else if( action == eCreate )
{
assert( inst == 0 );
inst = impl;
}
else
{
assert( action == eDestroy );
assert( inst );
inst = 0;
}
return static_cast<T*>(inst);
}
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
template <class T>
SingleIF<T>::SingleIF( T& impl )
{
SingleIF::doAction( eCreate, &impl );
}
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
template <class T>
SingleIF<T>::~SingleIF()
{
SingleIF::doAction( eDestroy );
}
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
template <class T>
T& SingleIF<T>::get()
{
return (*SingleIF::doAction( eGet ) );
}

.... and is usually used like this (This is an interface
specification):

class MyInterface : public SingleIF<MyInterface>
{
public:
virtual void method1() = 0;
virtual void method2() = 0;
virtual void method3() = 0;

protected:
~MyInterface(){ } //Could be virtual to prohibit compiler warnings
MyInterface(): SingleIF( *this ){ }
};

BTW, I know it does have some caveats that I can think of (slicing at
the
end of its life (an obvious one) ), but in general it seems to reduce
all this
associative code required to get the right "concrete" at the right
place. For
me it seems a simpler solution than factories and in general it works
very well, especially if you want only one instance (or
implementation) of
an interface - something that I've seemed to require often.

Regards,

Werner

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FWSM/PIX and Dynamic PAT using global IP range vs. global interface vs. global IP Hoffa Cisco 1 10-25-2006 06:50 PM
FWSM/PIX and Dynamic PAT using global IP range vs. global interface vs. global IP Hoffa Cisco 0 10-25-2006 01:04 PM
Could not load type 'Global.yaddayadda'. - Global.asax.cs Daniel Bass ASP .Net 2 12-31-2003 03:57 PM
Global variables on par with ASP's global.asa Wayne ASP .Net 2 11-11-2003 10:58 PM
Global Error handling in Applicatio_Error() of Global.asax VSK ASP .Net 1 07-29-2003 03:12 AM



Advertisments