1

Possible Duplicate:
How do I prevent a class from being allocated via the 'new' operator? (I'd like to ensure my RAII class is always allocated on the stack.)

Suppose I define a class in the library

class Base {};

and I publish the class to the users.

And one user defines a new class

class Derived : public Base {}

The question what can I do in Base to prevent users create an instance of Derived on heap?

For example, this is allowed

Derived dd;

This is not

Derived* dd = new Derived();

Thanks,

Community
  • 1
  • 1
jerry
  • 355
  • 1
  • 6
  • 13

3 Answers3

9

I think the best you can do is to declare a private operator new (I can't recall if this is needed but you'll probably want to do all three: normal, array, and placement) in your base class. The user can still get around this by creating their own operator new in the Derived class but at least they have to think about it and actively work to subvert your intention.

If you're worried about non-accidental problems with creating your class on the heap (for example malicious developers of child classes), C++ is not the language for this project. It's powerful and has lots of places where your have to rely on your end-programmers not bypassing the intentions.

Mark B
  • 95,107
  • 10
  • 109
  • 188
4

You make operator new private in the base class.

class Base {
    void* operator new(size_t);
};
class Derived : public Base {
}

//...

Base* p = new Derived; //ERROR
Derived d;             //OK
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

In addition to making the new operator private in Base, you can give a reminder to the user of Base what the intention of Base is. This way, a developer using Base can't claim the intentions were not documented.

class Base
{
    void * operator new (size_t) {}
    void * operator new[] (size_t) {}
    void * operator new (size_t, void *) {}
protected:
    struct I_promise_not_to_dynamically_allocate_Base {};
    Base (I_promise_not_to_dynamically_allocate_Base) {}
    virtual ~Base () {}
    //...
};

Now, when the developer uses the Base, they are forced to pass in the argument:

class Derived : public Base
{
public:
    Derived () : Base(I_promise_not_to_dynamically_allocate_Base()) {}
    //...
};

As already stated, nothing prevents the the developer from overloading new and delete themselves, but then they would be breaking a promise!

jxh
  • 69,070
  • 8
  • 110
  • 193