0

I know that maybe this is not the best design in the world, but i interested in the answer without any practical reason.

Let assume i have these two class with overloaded new methods:

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

class Child : public Base {
public:
operator void* new(size_t); //THIS, i would like this to be the "original" new.
};

operator void* Base::new(size_t) {
//...
return new Child;
//...
}

I would like Child::new to work like the original new, so i could avoid using malloc.

Is there a way to do it?

Thanks ahead!

casperOne
  • 73,706
  • 19
  • 184
  • 253
  • This [link](http://blogs.msdn.com/b/calvin_hsia/archive/2009/01/19/9341632.aspx) might help you... – niktehpui Mar 28 '12 at 04:59
  • I don't think your `Base::operator new` really 'works' (e.g. each time a `Child` is constructed it's not destroyed). Given that, it's hard to tell what you want `Child::operator new` to do. Are you sure you're not looking for factory functions? – Luc Danton Mar 28 '12 at 05:06
  • Good Read: [How should I write ISO C++ Standard conformant custom new and delete operators?](http://stackoverflow.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom-new-and-delete-operators). I fail to understand what you ar trying to achieve So I restrain from marking this as duplicate, I do have a feeling it is what you are looking for. – Alok Save Mar 28 '12 at 05:13

2 Answers2

2

It's not a correct design. An operator new function is supposed to return raw memory, not a constructed object. If your goal is for an invocation of new Base to in fact create a new Child, it can't be done in C++; the usual solution is to provide a factory method in Base; e.g.:

class Base
{
    //  Ban the expression `new Base`...
    void* operator new(size_t);
protected:
    virtual ~Base();  //  Ban instances on the stack.

public:
    static Base* create(/*...*/);
    //  ...
};

Then in the source file:

class Child : public Base
{
    //  ...
};

Base* Base::create(/*...*/)
{
    return ::new Child(/*...*/);
}

(Note that the private operator new doesn't totally ban client code from using the new operator, since one can always write ::new Base.)

Other than declaring a private operator new to ban direct allocation, the only use of operator new members is to allocate instances from a specific pool; in which case, you also need a member operator delete function to free them to the pool.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

You can always access global operator new using the syntax

return ::operator new( sizeof Child );

Note the unary scope operator. This syntax ignores any class and namespace members, and will work within either Base::operator new or Child::operator new.

To allocate and initialize the object without using class/namespace members, use

::new Child

Aside from that… yes, member operator new is usually a serious code smell.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • I'd recommend calling `operator new`. – Luc Danton Mar 28 '12 at 05:16
  • @LucDanton Yeah, caught that shortly after re-reading it. Mind isn't at full speed yet apparently. Also this is stinky. – Potatoswatter Mar 28 '12 at 05:18
  • @Potatoswatter: Thanks! :) This is what i wanted. I will look the other links, because this is really a smelly thing. :) –  Mar 28 '12 at 05:24
  • 1
    Why is a member `operator new` a problem? It's a simple way to ensure that a memory pool is used for the class, for example. (Obviously, an `operator new`, member or otherwise, should never use the `new` operator, since its role is to return raw memory, not a constructed object.) – James Kanze Mar 28 '12 at 08:28
  • @JamesKanze but he's obviously not implementing his own allocator. – Potatoswatter Mar 28 '12 at 10:12
  • @Potatoswatter That's the impression I got as well, which is why my answer mostly addresses what I sort of guess he is trying to do. But the fact that he is misusing the feature doesn't mean that it smells; class specific `operator new` is a standard idiom for memory pools. – James Kanze Mar 28 '12 at 12:13
  • @JamesKanze It is useful, but that idiom implies that either the allocator is hard-coded to the allocated class, because otherwise `operator new` should be a free function found by ADL on placement syntax, or that it's a singleton if placement syntax would be inapplicable. C++11 also adds TLS, allocators make relatively unsmelly singletons, and you could have a member `operator new` dispatch to a default, not singleton, pool… but taken alone, I still wouldn't call it the idiomatic primary alternative. – Potatoswatter Mar 28 '12 at 13:51
  • @Potatoswatter We're talking about member `operator new` here, so they are members of the class. Lookup for `operator new` is a little different than for other things, ADL doesn't play a role, and the `operator new` function must be either a member or in the global namespace. – James Kanze Mar 28 '12 at 15:22
  • @JamesKanze "A little" ADL is used. The name is looked for in the global namespace under overload resolution, so a `friend` should be found. Anyway, even sans ADL, I stand by the same argument. – Potatoswatter Mar 28 '12 at 15:31
  • 1
    @Potatoswatter That's not what the standard says. When you want a class specific `operator new` function, it has to be a member of the class or a base class of the class. And you'll have to provide a corresponding `operator delete` function. – James Kanze Mar 28 '12 at 15:34
  • 1
    @JamesKanze Nah, I'm wrong, it's really best to use a member placement `operator new` to dispatch to the allocator. Without that the user can accidentally use another allocator. It does still work the other way, though, even including the placement delete. – Potatoswatter Mar 28 '12 at 15:38
  • 1
    @Potatoswatter Attention with placement delete. It is only used in the special case where the constructor in a `new` expression throws. The `operator new` function which was used in the `new` expression is not memorized. – James Kanze Mar 28 '12 at 18:03