1

Is there a way to design a class, that neither it nor its descendants can be allocated automatically (on stack), but only dynamically (in heap)?

I have a 3D scene represented by a scene tree, each object has a parent and a number of children. All scene objects are inherited from some base class SceneObject. I would like to make it impossible to allocate such objects on the stack.

The only way I know to achieve this for a class is to declare a protected constructor and provide a factory (see Is it possible to prevent stack allocation of an object and only allow it to be instantiated with 'new'?). This does indeed work as I want for the class, but not for its descendants. Authors of derived classes need to explicitly declare constructors as non-public and I have no way to control it, thus providing possibilities for an error.

Are there any possibilities to achieve what I want? Any compromises maybe?

Community
  • 1
  • 1
Mikhail
  • 20,685
  • 7
  • 70
  • 146
  • 2
    Compromise: Don't design a class so badly that it can't be instantiated on the stack. That's a sign that you've done something very badly. – Puppy Aug 11 '15 at 19:56
  • 1
    @Puppy I agree. The truth is that the class is already designed, what I can do is to create some kind of wrapper with minimum interference with existing code. – Mikhail Aug 11 '15 at 20:10
  • @EdHeal This is a possible compromise, I think. In order to make this work as I want, we need to hide derived types from client code at all and make them available to the factory code only. However, this will disallow to use template functions as factories and will require the factory to see all the types. It is a good fit for C interfaces, but I think not a good solution for C++ code. – Mikhail Aug 11 '15 at 20:20
  • An interface pattern as well to decouple – Ed Heal Aug 11 '15 at 20:23
  • @EdHeal In case I understand your idea (and I'm not completely sure I do) it will require major change in existing architecture, which we cannot afford. – Mikhail Aug 11 '15 at 20:31
  • Refactoring is an option – Ed Heal Aug 11 '15 at 20:44

2 Answers2

0

Not really, no.

You may be able to screw around with explicitly overriding operator new, or to mix the answer you linked to with templates, but otherwise you're hosed.

I'm going to go off on a limb and guess that your full problem involves resource management; if that's the case, check out the rule of three; if your class has a user-defined destructor, copy constructor, or copy assignment (operator=(const Something&)), you probably need all three.

JesseTG
  • 2,025
  • 1
  • 24
  • 48
0

The only way I know to do this is how your linked answer says - declare the class's constructor as private so nobody but the class itself can create instances of it, and then provide a public static method that creates an instance of the class on the heap. Everyone who wants an instance must call the static method.

Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • How am I supposed to call `private` constructor from derived classes? – Mikhail Aug 11 '15 at 20:14
  • You don't. You would have to design a class factory where the classes register creator functions for themselves (so they can call their own private constructors), and then users have to ask the factory for an instance of the desired class, and the factory calls the appropriate creator. Otherwise, if you make the constructor `protected`, descendants can call it in their constructors, but then there is nothing to stop someone from creating a descendant with a public constructor and then create instances of that class on the stack. – Remy Lebeau Aug 11 '15 at 20:21
  • Agree, but I still cannot get how I can inherit from a class with private constructor? – Mikhail Aug 11 '15 at 20:25
  • The only way is if the derived class is declared as a `friend` of the base class. Otherwise, the base class constructor must be either `public` or `protected`. – Remy Lebeau Aug 11 '15 at 20:31
  • And after that "descendants can call it in their constructors, but then there is nothing to stop someone from creating a descendant with a public constructor and then create instances of that class on the stack". Thus I see no reason in private constructor at all. – Mikhail Aug 11 '15 at 20:33