views:

269

answers:

6

I have an object that requires a slightly different construction wether it's instance is staticly or dynamically allocated. The object should only have a single default constructor. So having two constructors, one for each case, and having the user explicitly select the proper constructor is out of the question.

Is there any proper way to acheive this?

That's how I do this at the moment: I overload the new operator for that object, malloc the memory, and use the returned pointer as a pointer to the (yet un-initialized) instance, and set a specific data member of the object to some magic-value. Then, within the consutrctor, I check the value of the member. If it's the magic-value, then the object is 99.9% dynamically allocated.

This method haven't yet failed for me under either relase and debug modes, however, it seems like a terrible hack.

+3  A: 

There's not really a portable way to do this.

Why do you want to, anyway? Seems like a design problem......

Eric H.
Actually, to expand on my answer, Scott Meyers devotes pages and pages to this in Item #27 of More Effective C++. You can't do what you want (figure out in the constructor whether you're heap based on not), but you *can* design your objects to be "heap only" or "stack only" (with some inheritence caveats).
Eric H.
why didn't you just edit your answer?
Carson Myers
Oh... heh.... because I didn't see that button. I was trying to edit a comment earlier (apparently you can't), so when I got around to editting the answer I just assumed (like a moron!) that I couldn't.Executive summary: because I'm a noob.
Eric H.
A: 

Overloading new sounds like a reasonable thing to do. I can't see another way of doing it.

Magnus Skog
A: 

As you allude to in your question, this method isn't guaranteed to work; what if the data member, by sheer chance, has the magic value?

There is no portable way to do what you want. You have to either live in fear and uncertainty or change your design. Sorry.

David Seiler
A: 

Any constructor can be used for static or dynamic allocation. There is no way for you to force the user of the object to use a particular constructor, whichever way he allocates the object.

Dima
+1  A: 

You should be able to achieve what you want while leaving a single user-accessible default constructor (which will be used for static and auto objects -- you appear to ignore the existence of auto objects, e.g. local variables, so I imagine you want to treat these cases the same).

Make operator new and a separate constructor both private, and make a public static method (it's a case of the "factory method" design pattern) which only does a return new TheClass(123); (assuming the separate constructor takes for example an integer, but of course you can pick any type of argument you want, as the argument isn't used anyway).

You know you said the object should have a single constructor, but from the user's point of view that's exactly of the class is behaving, and there's no "explicit selection of constructor" on the user's part (he just can't call new explicitly but must go through your supplied factory method, that's all).

Alex Martelli
I am not sure I got that. Do you mean that the user would have to call the static function in order to allocate a new instance instead of using new? If that's what you mean, then why overload new at all? Anyways, that won't do, because the class needs to be inherited, and by your method each sub-class should also define it's own static-function. * As you mentioned, auto objects are treated as static for that matter.
Making new private blocks the user from just calling `new Foo()` as they otherwise might. And yes, if _all_ Foo objects living in dynamic storage (including as base classes or members) need special treatment, then my suggestion requires other classes to do likewise -- but your proposed solution doesn't work any better then!-)
Alex Martelli
A: 

I don't think you can tell in the constructor.

I don't know if this helps, but you can prevent the object from being statically created by making the destructor private. You would also need to have a public "Delete" method that does a delete this for code that dynamically allocates objects of this class -- they would have to do an obj->Delete() rather than delete obj.

Graeme Perrow
This doesn't work at all in a base class. A private destructor would prevent the subclass object from ever existing.A protected base class destructor can be called from its children, which means the subclass can be made on the stack. Unless the subclass also limits its dtor visibility. Either way a protected dtor on the base class is useless.
Mark Borgerding