2

Considering class A, I would like to limit its creation to new. That is

A* a = new A; // Would be allowed.
A a;  // Would not be allowed.

How could this be accomplished?

octopusgrabbus
  • 10,555
  • 15
  • 68
  • 131
learning
  • 94
  • 6
  • 1
    It is possible in a round about way, but why do you need that? – juanchopanza May 18 '12 at 11:46
  • It would be a really really bad idea. You'd be creating a class which can *only* be used from really bad code. Unless you're *trying* to ensure the presence of bugs in your code, don't do it – jalf May 18 '12 at 11:49
  • @jalf: I agree with the sentiment, but I think your claim is a *bit* broad. :) – John Dibling May 18 '12 at 13:07
  • @jalf: It's very useful in embedded work. If you have written a particularly heavyweight class you can prevent other developers from blowing the stack by enforcing the creation of any instances on the heap. – Ant May 18 '12 at 13:39
  • @Ant: and you also prevent them from putting it in (heap-allocated) classes, or in a vector, for example. In other words, it's very useful if you're working with incompetents. but it also forces any competent developers you might have to write terrible code. – jalf May 18 '12 at 13:59
  • @jalf: Same thing applies for vectors - if the class is large enough to cause an overflow when created on the stack, you probably don't want the vector class making hundreds of instances of it on the heap as the size of the vector increases. – Ant May 18 '12 at 14:15
  • errm, wha'? That makes no sense at all. – jalf May 18 '12 at 17:38
  • @jalf: You have a 128 byte stack and 128 kilobytes of RAM. You want to create a vector of 129 objects, each of which consumes 128 bytes. A pointer to each of these objects consumes 4 bytes. When you add 129 pointers to a vector you consume (4 * 256) bytes, because a vector doubles in size when it hits its max. If you add 129 objects to the vector it will consume (128 * 256) bytes. One of these scenarios is totally unacceptable. – Ant May 18 '12 at 23:53
  • Have you ever heard of `std::vector::resize`, by any chance? If you know you need 129 elements, create a vector with size 129. Also, most vector implementations do not double in size when you push elements onto them. (And apart from that, I think your scenario is sliiiiightly theoretical. How often do you (1) work on an embedded device with a very small amount of RAM, and (2) fill an appreciable fraction of that with a single array of very large objects? Not every day, I wager) – jalf May 19 '12 at 08:17
  • Which is precisely why it's nice to be able to throw up a big warning sign in the rare situations when you're about to do that, because it's the last thing the average programmer would expect to happen. – Ant May 21 '12 at 03:07

6 Answers6

8

You could make the constructor private and provide a static factory method that returns a dynamically allocated instance:

class A
{
public:
    static A* new_instance() { return new A(); }
private:
    A() {}
};

Instead of returning a raw pointer, consider returning a smart pointer instead:

class A
{
public:
    static std::shared_ptr<A> new_instance()
    {
        return std::make_shared<A>();
    }
private:
    A() {}
};
hmjd
  • 120,187
  • 20
  • 207
  • 252
5

One option is to make the constructor(s) private, and use a static helper function:

class A {
private:
    A() {}          // Default constructor
    A(const A &a);  // Copy constructor

public:
    static A *create() { return new A; }
};

...

A a;                // Won't compile
A *p = A::create(); // Fine

Although you should strongly consider returning a smart pointer rather than a raw pointer.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
4

Yes, you can do so using the factory pattern.

class A
{
    A() {}  //private by default
    friend struct AFactory;
};
struct AFactory
{
    static A* newA() { return new A; }
};

or a similar static member function.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
1

This is actually very simple. Make your destructor private. Objects with private destructors cannot be created on the stack, so the only way to create them is via a call to "new". You'll need to provide another mechanism for deleting the object, such as a "delete()" method that calls "delete self".

Ant
  • 4,890
  • 1
  • 31
  • 42
0

I assume you are trying to control what a client can do with your class. The answers here make use of slightly arcane techniques. A common way of segregating systems is to use interfaces.

You could make A abstract:

class A
{
public:
    virtual void doSomething() = 0;
    virtual ~A() {}
};

And make at least one implementation:

class A_impl : public A
{
public:
    virtual void doSomething()
    {
         // behaviour
    }
};

Then return an instance of A_impl to the client using a (smart)pointer as the other answers suggest.

Peter Wood
  • 23,859
  • 5
  • 60
  • 99
-1

Can you not just do:

A* a;

? That is just declaring a pointer to an A object. It hasn't been initialised though so you should probably do

A* a = NULL;

That is a pointer to an object of type A but points to a known (non)value.

EDIT: Perhaps I'm not grasping the full question given the complexity of the other answers here.

EDIT2: Is he asking if you can prevent creation of object on the stack and only allow heap created objects and access via pointers? If that is the case my vote goes to a factory pattern.

Dennis
  • 3,683
  • 1
  • 21
  • 43