Global objects...

Discussion in 'C++' started by Phlip, Sep 19, 2007.

  1. Phlip

    Phlip Guest

    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
    Phlip, Sep 19, 2007
    #1
    1. Advertising

  2. Phlip

    barcaroller Guest

    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.
    barcaroller, Sep 19, 2007
    #2
    1. Advertising

  3. * 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?
    Alf P. Steinbach, Sep 19, 2007
    #3
  4. Phlip

    werasm Guest

    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
    werasm, Sep 20, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VSK
    Replies:
    1
    Views:
    755
    Alvin Bruney
    Jul 29, 2003
  2. Wayne
    Replies:
    2
    Views:
    453
    Wayne
    Nov 11, 2003
  3. Daniel Bass
    Replies:
    2
    Views:
    6,846
    Daniel Bass
    Dec 31, 2003
  4. 2obvious

    no global constants in global.asax?

    2obvious, Sep 4, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    1,788
  5. 7stud
    Replies:
    11
    Views:
    661
    Dennis Lee Bieber
    Mar 20, 2007
Loading...

Share This Page