7

I'm using a C++ base class and subclasses (let's call them A and B for the sake of clarity) in my embedded system.

It's time- and space-critical, so I really need it to be kind of minimal.

The compiler complains about lack of a virtual destructor, which I understand, because that can get you into trouble if you allocate a B* and later delete the pointer as an instance of A*.

But I'm never going to allocate any instances of this class. Is there a way I can overload operator new() such that it compiles if there's no dynamic allocation of either class, but causes a compiler error if an end user tries to allocate new instances of A or B?

I'm looking for a similar approach to the common technique of "poisoning" automatic compiler copy constructors via private constructors. (e.g. http://channel9.msdn.com/Forums/TechOff/252214-Private-copy-constructor-and-private-operator-C)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • The last part of your post makes me wonder if you're in need of a Singleton Pattern implementation.http://en.wikipedia.org/wiki/Singleton_pattern – Rycul Jun 07 '11 at 21:05
  • @Rycul: Thanks, they're not singletons, it's just that in small embedded systems we tend to do almost everything with static or stack allocation. – Jason S Jun 07 '11 at 23:26
  • Just for curiosity. I don’t understand, why do you need a virtual destructor at all? Just because you are deriving doesn’t mean you need a virtual destructor. Do you have any other virtual function? How are you going to use such function if you are not going to use it dynamic memory in the first place? – alfC Jul 08 '19 at 09:01
  • @alfC: reread: "The compiler complains about lack of a virtual destructor." – Jason S Jul 10 '19 at 16:49
  • p.s. keep your expectations low for responses to comments on questions that were asked many years ago – Jason S Jul 10 '19 at 16:52
  • @JasonS, yes, but my guess is that the compiler complained because you had at least one virtual function already. no? and then my question was, why do you have virtual function in the first place in you never were going to use the object polymorphically. – alfC Jul 10 '19 at 18:52
  • I have no idea, it was 8 years ago... but I don't think I had any virtual functions. This was MS Visual C++, not sure which version but probably MSVC 2005 oh right, it was an embedded system. Then it would have been TI's C2000 compiler. And no, I wasn't using virtual functions. – Jason S Jul 10 '19 at 19:52

3 Answers3

9

You can poison operator new in just the same way as you can a copy constructor. Just be sure not to poison placement new. A virtual destructor would still be a fine recommendation.

int main() {
    char data[sizeof(Derived)];
    if (condition)
        new (data) Derived();
    else
        new (data) Base();
    Base* ptr = reinterpret_cast<Base*>(&data[0]);
    ptr->~Base();
}
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • "A virtual destructor would still be a fine recommendation." -- it would be, except that w/o dynamic memory allocation it won't be used, and the memory costs in this one class are too high. (otherwise I'd just stick an empty virtual destructor there and be done with it.) – Jason S Jun 07 '11 at 21:08
  • @Jason S: I wouldn't be so sure about that. Dynamic allocation does not always mean just the heap - it can also mean placement new. I could easily create an example which wouldn't use any dynamic memory allocation and still depended on a virtual destructor. If you absolutely can't use one, then poison placement new too. – Puppy Jun 07 '11 at 21:11
  • do you know any "simple" cases that use placement new w/o dynamic memory allocation? This is a processor with relatively limited memory + no standard library (so STL isn't here; we're not using stacks or queues or things). – Jason S Jun 07 '11 at 21:23
  • @Jason: Just posted one. I guess that if you know for sure that you're writing every line in your program, you could avoid it, or just poison placement new, but that code is undefined without a virtual destructor. – Puppy Jun 07 '11 at 21:47
  • Well, I suppose I could make the destructor private also. – Jason S Jun 07 '11 at 22:27
  • @Jason S: You'd need `protected` - else how can the Derived class call it in it's destructor – Puppy Jun 07 '11 at 22:27
  • ah, true; good point. Although in this case the destructors are always empty, they're just there to prevent the compiler warning. – Jason S Jun 07 '11 at 22:34
  • Technically this is UB, you should assign the result of the new-expression to `ptr`, or use `std::launder` . Also the code snippet doesn't seem to have anything to do with the poisoning. I'm guessing it is meant to be a unit test that you didn't accidentally poison placement-new; maybe it'd be good to add some more explanatory text with the code sample – M.M Jul 08 '19 at 04:42
2
class A
{
private:
    void *operator new(size_t);
    ...
};

The elipses are for the other overrides of operator new and the rest of the class.

MSN
  • 53,214
  • 7
  • 75
  • 105
0

Just make operator new private

C.J.
  • 15,637
  • 9
  • 61
  • 77