abstract factory question

Hi People,

I'm trying to create an abstract factory but I'm stuck.
I create a component factory
1
2
3
4
5
6
7
8
class Component {
public:
    virtual ~Component();
    //Abstract constructor: takes a bool for gpu, and component parametermap 
    static Component* make(bool, QString);

   //HOW TO CALL runProc??

then subclas this:
1
2
3
4
5
class cpu_Component: public Component {
public:
    static Component* make(QString);
    virtual void runProc(QList<Mat>*) = 0;
    friend class Component;


and

1
2
3
4
5
class gpu_Component: public Component {
public:
    static Component* make(QString);
    virtual void runProc(QList<GpuMat>*) = 0;
    friend class Component;


My question is how can I have the Component class know about the runProc method ofwhich the type on which it opperates differs depending on the subclass??



For the completion:
elsewhere, I have defined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Component* Component::make(bool gpu, QString name) {
    if (gpu) {
        return gpu_Component::make(name);
    } else {
        return cpu_Component::make(name);
    }
    return NULL;
}

Component* cpu_Component::make(QString name) {
    if (name == "framegrabber") {
        return new cpu_FrameGrabber();
    }
    if (name == "framemerger") {
        return new cpu_FrameMerger();
    }
    if (name == "colorspace") {
        return new cpu_ColorSpace();
    }
    return NULL;
}

Component* gpu_Component::make(QString name) {
    if (name == "framegrabber") {
        return new gpu_FrameGrabber();
    }
    if (name == "framemerger") {
        return new gpu_FrameMerger();
    }
    if (name == "colorspace") {
        return new gpu_ColorSpace();
    }
    return NULL;
}


these objects actually implement runProc depending if their cpu or gpu counterpart is requested
Last edited on
Why not make runProc() a pure virtual function of Component?
because the typename of it's parameter differs depending on the gpu or cpu variant being used, i.e.
virtual void runProc(QList<GpuMat>*) = 0;
and
virtual void runProc(QList<Mat>*) = 0;

if my reply has no merrit, how would i go about implementing the solution
Ah, missed that part. Indeed it is a problem. What you need is a common ground for the parameter:

1
2
3
4
5
6
7
class ListBase
{
public:
    //Add here pure virtual functions that both list types can fulfill.

    //The above is not too important.  If irreconcilable, just use this class as base and do dynamic_cast.
};


Now you just pass the pointer or reference to a list of type ListBase instead of QList<T>. If you can reconcile the methods inside of each list (which I presume you can since both differ by the data type of T only), then you can even write a generic runProc()! But, if you cannot, you can, in each corresponding class, do a dynamic_cast<QList<T>*>(param) and do the specific calls that you need.
Ok,

here is what I have

1
2
3
4
5
6
class ListBase
{
public:
    virtual void runProc(QList<gpu::GpuMat>*)=0;
    virtual void runProc(QList<Mat>*)=0;
};


this produces an error when:

1
2
3
4
5
6
7
class Component {
public:
    virtual ~Component();
    //Abstract constructor: takes a bool for gpu, and component parametermap 
    static Component* make(bool, QString);
    virtual void runProc(ListBase) = 0;
}


how and when exactly must I do this dynamic casting?
is something like this correct?

1
2
3
4
5
6
7
8
9
class cpu_Component: public Component {
public:
    static Component* make(QString);
    virtual ~cpu_Component();
    virtual void compSetup()=0;
    virtual void runProc(dynamic_cast<QList<ListBase>*>(Mat)) = 0;
    friend class Component;
 }



I thought runProc() was a method of the Component-derived classes only. Why does ListBase have those? I meant this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class ListBase { virtual ~ListBase() { } };

template<class T>
class QList : public ListBase
{
    ...
};

class Component
{
public:
    virtual ~Component();
    virtual void runProc(ListBase&) = 0; //Note that the parameter here is by reference, unlike your post which is just a copy.
    //Your copy would produce object slicing.
};

class cpu_Component : public Component
{
public:
    virtual void runProc(ListBase &list)
    {
        //Dynamic cast:
        QList<Mat> &theList = dynamic_cast<QList<Mat>&>(list); //Again, note this is a reference.
        //Now use theList instead of list to perform whatever you need to perform.
        ...
    }
};


As you can see, my base ListBase class does not provide any method except the virtual destructor (so dynamic casting is possible). If you could abstract away the usage of QList<>, then ListBase could list the methods required for runProc() and you probably can program a generic runProc() inside the Component class, as opposed to having to program one for each of the derived classes.
I would like to thank you for your help, after taking a beating from the debugger I think everything is working now

Topic archived. No new replies allowed.