C ++: references and factories

I have something like this:

struct D {
    virtual void operator() {...};
}
struct D1 : public D {
    virtual void operator() {...};
}
struct D2 : public D {
    virtual void operator() {...};
}

void foo(D &d) {...};

      

And that's fine, and controls my D's lifecycle nicely:

foo(D());
foo(D1());
foo(D2());

      

But I choose my variant D in several places, so I need a simple factory:

const D& make_D()
{
    // BAD, returning reference to temporary
    if(is_tuesday())
        return D1();
    return D2();
}

      

Instead of returning a reference to a temporary one, I could return an object, but then I'll go to the base class. Alternatively, I could return a pointer from my factory, but then the client has to delete it. Other, more complex decisions also impose more burden on the client.

Is there a way to write something like

D& d = make_D();
foo(d);

      

(or even foo(make_D())

)? The goal is to wrap the complexity in the various definitions of D and in make_D()

so that functions like foo()

that, and those who call those functions, don't have to worry about it.

+3


source to share


3 answers


The usual way is to either return a pointer or a smart pointer.

The disadvantage of using a pointer allows the user to manage their memory.



If you return a smart pointer, that's no longer a problem.

const SmartPtr<D> make_D()
{
    if(is_tuesday())
        return SmartPtr(new D1());
    return SmartPtr(new D2());
}

      

+5


source


Unfortunately this is not possible.

I usually use std::unique_ptr

(sometimes std::shared_ptr

when not possible to use std::unique_ptr

):



typedef std::unique_ptr< D > Dptr;
Dptr make_D()
{
    Dptr p( nulptr );

    if(is_tuesday())
        p.reset( new D1 );
    else
        p.reset( new D2 );

    return p;
}

      

+5


source


First, I'm not too sure I understand. The code you provided is not legal and will not compile. Are you sure it is not:

struct D
{
    virtual void operator()() const { /* ... */ }
};

      

and

void foo( D const& d ) { /* ... */ }

      

or is it changed? (Presumably not, since you are not passing the arguments, and you are disposing of the object after use.) If not, then you can simply return references to static instances. This is the usual solution I use. Otherwise, it is possible to make an object that can be copied behave polymorphically using the literal envelope idioms, but this is a bit of work and has significant run-time overhead since it usually requires cloning the actual object for each copy.

0


source







All Articles