Design pattern for overloading new and delete operators [C++]

Started by
5 comments, last by obhi 13 years, 4 months ago

Hi,
All classes in one of my program derive from certain base class which overrides the new and delete operators. There are multiple such base classes depending upon the type of class deriving it. I am having trouble however with the design decision. Let me explain my problem with an example:

[source lang='C++']class ABase{public:	void* operator new(size_t s) {			return MemoryManagerForA::Alloc(s);	}	void operator delete(void* ptr) {		MemoryManagerForA::Free(ptr);	}};class BBase{public:	void* operator new(size_t s) {			return MemoryManagerForB::Alloc(s);	}	void operator delete(void* ptr) {		MemoryManagerForB::Free(ptr);	}};class A : public ABase{protected:	int a;public:	A() {		a = 10;	}};class B : public BBase{protected:	int b;public:	B() {		b = 10;	}};class C : public A, public B{	int c;public:	C() {		c = a + b;	}};


The problem is with class C in the above code. There is a clear ambiguity as to which operator it must call. So if I write 'new C()' it will throw me a compilation error. Is there any workaround to this problem given I need this design pattern in which there must be multiple base classes for C?

Further I cannot inherit the base classes at level 'C'. (This design may be flawed because if I delete a pointer of class C type-casted as A or B, the proper free might not be called). I am not sure how to go around this problem.

Any help will be much appreciated.

Thanks,
obhi

What if everyone had a restart button behind their head ;P
Advertisement
My first instinct is to tell you to avoid multiple inheritance as that will help you avoid a plethora of design issues that arise because of its use. I believe you will find that you have a much easier time working with your class hierarchy if you do this. Use interfaces instead, which you can emulate in C++ rather easily.
I'm not an expert at this, but having a single object handled by two different memory managers obviously won't work, so if you instead create a BaseBase class that handles the memory managing, and have class ABase/BBase : public virtual BaseBase, then you won't have that problem.
Another option would be a C* CreateC() function that handles the memory management with placement new.
If you need B to be handled by a different memory manager than A sometimes, but by the same one if used through C, then perhaps declare the memorymanaging baseclass through a template, such as template<class MemoryManager> class BBase : public virtual BaseBase<MemoryManager> or similar.
I do use interfaces. But it helps sometimes to wrap common functionalities in classes rather than pure interfaces.

So there are instances where I am using classes. And yes this has caused a serious design issue. I am now considering sorting this out completely. May need a whole lot of design changes. I am just hoping I could avoid that altogether.
What if everyone had a restart button behind their head ;P
Quote:Original post by Erik Rufelt
I'm not an expert at this, but having a single object handled by two different memory managers obviously won't work, so if you instead create a BaseBase class that handles the memory managing, and have class ABase/BBase : public virtual BaseBase, then you won't have that problem.
Another option would be a C* CreateC() function that handles the memory management with placement new.
If you need B to be handled by a different memory manager than A sometimes, but by the same one if used through C, then perhaps declare the memorymanaging baseclass through a template, such as template<class MemoryManager> class BBase : public virtual BaseBase<MemoryManager> or similar.


In-fact I dont even need to derive BaseBase virtually to work that out. But I do have multiple base classes and I am using templates already. But if the memory manager changes, so does the base class. Anyway I am fixing the problem the hard way. I am changing some design patterns. I guess thats the only way.

Thanks for your replies guys.
What if everyone had a restart button behind their head ;P
Quote:Original post by obhi
I do use interfaces. But it helps sometimes to wrap common functionalities in classes rather than pure interfaces.

So there are instances where I am using classes. And yes this has caused a serious design issue. I am now considering sorting this out completely. May need a whole lot of design changes. I am just hoping I could avoid that altogether.


Then perhaps you should consider composition instead of inheritance? I know that multiple inheritance can often be an easy solution to a problem, but it is usually the least correct according to OO principles, and is almost always the least maintainable approach.

If you use composition, you can keep the construction of the different objects separate from the construction of the container class.
Quote:Original post by arbitus
I know that multiple inheritance can often be an easy solution to a problem, but it is usually the least correct according to OO principles, and is almost always the least maintainable approach.


I 100% agree with that. But there are situations in which composition won't work or will require some manipulation. Say, if I want to derive a class whose, say, Update method I wanted to override, using composition I will require to create a new class and add it as a member. This is okay unless the override implementation will also depend on other members of the composing class. Even that can be worked out, but at times the easy way out is to just go for multiple inheritance.

I used to keep an open mind about inheritance, but I guess having some strict rules help in the long run.

Thanks again.
obhi

What if everyone had a restart button behind their head ;P

This topic is closed to new replies.

Advertisement