Consider the following class structure:
class Filter
{
virtual void filter() = 0;
virtual ~Filter() { }
};
class FilterChain : public Filter
{
FilterChain(collection<Filter*> filters)
{
// copies "filters" to some internal list
// (the pointers are copied, not the filters themselves)
}
~FilterChain()
{
// What do I do here?
}
void filter()
{
// execute filters in sequence
}
};
I'm exposing the class in a library, so I don't have control over how it will be used.
I'm currently having some design issues regarding ownership of the Filter
objects FilterChain
is holding pointers to. More specifically, here are two possible usage scenarios for FilterChain
:
- Scenario A: some of the functions in my library are constructing a (possibly complex) filter chain, allocating memory as necessary, and returning a newly-allocated
FilterChain
object. For example, one of these functions constructs a filter chain from a file, which can describe arbitrarily-complex filters (including filter chains of filter chains, etc.). The user of the function is responsible for object destruction once the job is done. - Scenario B: the user has access to a bunch of
Filter
objects, and wants to combine them in filter chains in a specific manner. The user constructsFilterChain
objects for its own use, then destroy them when he's done with them. TheFilter
objects must not be destroyed when aFilterChain
referencing them is destroyed.
Now, the two simplest ways to manage ownership in the FilterChain
object are:
FilterChain
own theFilter
objects. This means the objects referenced byFilterChain
are destroyed inFilterChain
's destructor. Which is incompatible with scenario B.FilterChain
does not own theFilter
objects. This meansFilterChain
's destructor does nothing. Now there is a problem with scenario A, because the user would have to know the internal structure of all theFilter
objects involved in order to destroy them all without missing one, as the parentFilterChain
does not do it itself. That's just bad design, and asking for memory leaks.
Consequently, I need something more complicated. My first guess is to design a smart pointer with a settable boolean flag indicating whether or not the smart pointer owns the object. Then instead of taking a collection of pointers to Filter
objects, FilterChain
would take a collection of smart pointers to Filter
objects. When FilterChain
's destructor is called, it would destroy the smart pointers. The destructor of the smart pointer itself would then destroy the object being pointed to (a Filter
object) if and only if the boolean flag indicating ownership is set.
I get the feeling that this problem is commonplace in C++, but my web searches for popular solutions or clever design patterns were not very successful. Indeed, auto_ptr
doesn't really help here and shared_ptr
seems overkill. So, is my solution a good idea or not?