views:

218

answers:

4

Hi, the following class hierarchies represent abstract resource handler and resource hierarchies. Both have the interfaces as base classes. Now imagine you write a system where you can implement multiple specific resource systems under these interfaces. Here is just one example. The specific main class creates the resources derived from stuff. Now when the created resource is handed to the base interface it is handed as a pointer to the base resource class but i want to handle the specific resource and have access to its specific attributes.

I know about double dispatch, but i don't think it works in this case. I would like to prevent RTTI and dynamic_casts. Do you have suggestions as to handle such cases?

class resource;

class main_resource_handler
{
public:
   virtual resource* create_resource() = 0;
   virtual void do_some(resource* st) = 0;
};

class resource
{
};

class specific_resource : public resource
{
public:
    int i;
};

class specific_resource_handler : public main_resource_handler
{
public:
    stuff* create_resource) {
        return new specific_resource);
    }
    void do_some(resource* st) {
        // in here i want to work with specific resource
    }
    void do_some(specific_resource* st) {
        // i want to get here
    }
}

main_resource_handler* handler = new specific_resource_handler();
resource* res = handler->create_resource();
handler->do_some(res); /// here
A: 

I wonder if the Curiously recurring template pattern is what you are looking for. There is already a thread on stackoverflow on this topic.

Vijay Mathew
A: 

I'm not sure why you need both the resource and the handler - it seems you're exposing an extra coupling to something with would be encapsulated. The problem wouldn't exist if create resource just returned a resource that the client could call methods on directly.

If you want safety, have the resource remember the address of the handler which created it, then check that in do_some(resource* st). If the resource was created by the current handler, and a handler can only create resources of a given kind, then it's safe to cast it and call the specific function. Though as above, if the function was just a virtual function on the resource it would be by definition type safe.

Pete Kirkham
+1  A: 

I think you're not asking the right question.

To do what you're asking, all you need is to add this:

template<typename T>
class helper : public main_resource_handler
{
public:
   virtual resource* create_resource() { return new T; }
   virtual void do_some(resource* st) { do_some_specific(static_cast<T*>(st)); }
private:
   virtual void do_some_specific(T* st) = 0;
};

And change this:

class specific_resource_handler : public helper<specific_resource>
{
private:
   virtual void do_some_specific(T* st) { ... }
}

The static_cast is only safe if you can guarantee that you will always call do_some on the right type of handler. But if you already know it's the right kind of handler, then there's no need to make a base-class method call. So presumably what you want is to get some sort of resource, not knowing its exact type, and pass it to the appropriate handler. That's trickier...

Dan
A: 

I think you may be looking for this:

http://www.artima.com/cppsource/cooperative_visitor.html

Noah Roberts