Passing a class to a pure virtual function (without templates)

Discussion in 'C++' started by captaincurk@googlemail.com, Apr 22, 2009.

  1. Guest

    Hello there,

    I have the following problem:

    // abstract base class
    class A {
    public:
    virtual void addItems() =0;
    };

    class B : public A {
    public:
    virtual void addItems() {
    // here I need to instantiate objects of a given type
    }
    }

    In B's something() function, I need to fill an internal list with
    objects of a specific type. I need some way to pass my classname to
    the function. Naturally I would try

    template <class InstantiationClass> virtual void addItems() {
    list.push_back(new InstantiationClass());
    }

    Unfortunately that does not work, because pure virtual template
    functions obviously don't work. Now I could move the template up to
    the class B, but that is not very useful, as in my main program I will
    call addItems very often and with different classes as parameters. Is
    there an easy way to do this?

    One way I could think of is to make a global constructor for each
    class I want to use and then pass a function reference, but that
    creates a LOT of new functions, which are only called once. And also
    since my code resides in a framework, the call to addItems should be
    very easy and straightforward and work with custom classes.

    Thanks in advance and cheers,
    Jonas
     
    , Apr 22, 2009
    #1
    1. Advertising

  2. Guest

    schrieb:
    > Hello there,
    >
    > I have the following problem:
    >
    > // abstract base class
    > class A {
    > public:
    > virtual void addItems() =0;
    > };
    >
    > class B : public A {
    > public:
    > virtual void addItems() {
    > // here I need to instantiate objects of a given type
    > }
    > }
    >
    > In B's something() function, I need to fill an internal list with
    > objects of a specific type. I need some way to pass my classname to
    > the function. Naturally I would try
    >
    > template <class InstantiationClass> virtual void addItems() {
    > list.push_back(new InstantiationClass());
    > }
    >
    > Unfortunately that does not work, because pure virtual template
    > functions obviously don't work. Now I could move the template up to
    > the class B, but that is not very useful, as in my main program I will
    > call addItems very often and with different classes as parameters


    Huh? What parameters? addItems doesn't take any parameters?

    >. Is
    > there an easy way to do this?


    If you really need a virtual method for adding some Items, but also
    have a lot of different things to create, you won't get a around class
    template. Remember that you'll need a vtable to make virtual methods
    work, and you only get a different vtable for each class you define.

    Your problem description reads very confusing. The method for adding
    new items takes no parameters, which is a bit odd. Probably that is
    the source of your problem. Try to write a short summary of what
    addItems should do, and most probably you'll see your problem.

    Regards,
    Stuart
     
    , Apr 22, 2009
    #2
    1. Advertising

  3. Guest

    Thanks Stuart!

    > Your problem description reads very confusing. The method for adding
    > new items takes no parameters, which is a bit odd. Probably that is
    > the source of your problem. Try to write a short summary of what
    > addItems should do, and most probably you'll see your problem.


    I'm sorry, while simplifying my example, I of course omitted a few
    details. I'll try to clarify:

    The addItems function takes a stream as parameter and extracts so-
    called "Types" from the stream, all of which are derived from a
    TypeBase. Inside class B I maintain a list of TypeBase*, which
    contains all ever added Types.

    I need to be able to do this:

    A* myObj = new B();
    B->addItems<Type1>(stream1);
    B->addItems<Type1>(stream2);
    B->addItems<Type2>(stream1);

    This is of course impossible, as I need addItems to be virtual,
    because myObj must be of type A* (because it is contained in a list of
    A*). But in the above example you can see, why I can't make B a
    template class, as the user will call addItems with different Types on
    the same B object.

    I would like to do something like

    B->addItems(stream1, (ClassPtr)Type1)

    but I don't know if that is somehow possible (I made (ClassPtr) up ;))

    Cheers, Jonas
     
    , Apr 22, 2009
    #3
  4. Guest

    [snip]

    wrote:
    > The addItems function takes a stream as parameter and extracts so-
    > called "Types" from the stream, all of which are derived from a
    > TypeBase. Inside class B I maintain a list of TypeBase*, which
    > contains all ever added Types.
    >
    > I need to be able to do this:
    >
    > A* myObj = new B();
    > B->addItems<Type1>(stream1);
    > B->addItems<Type1>(stream2);
    > B->addItems<Type2>(stream1);
    >
    > This is of course impossible, as I need addItems to be virtual,
    > because myObj must be of type A* (because it is contained in a list of
    > A*).


    There seems to be a conflict in semantics. I guess that the definition
    of A is given by the framework (IOW, you cannot change the "interface"
    A). This interface states that an object that implements this
    interface can load and add some items from a stream, and -- this is
    where I make a wild guess -- the object should be able to determine
    what to do _solely_ by looking at what the stream contains (there may
    be some magic numbers in the stream that tell you which data is
    inside). I further guess that your class B needs additional
    information about which types have been written into the stream. Is
    this right?

    Stuart
     
    , Apr 22, 2009
    #4
  5. Guest

    On Apr 22, 3:34 pm, wrote:
    > [snip]
    >
    >
    >
    > wrote:
    > > The addItems function takes a stream as parameter and extracts so-
    > > called "Types" from the stream, all of which are derived from a
    > > TypeBase. Inside class B I maintain a list of TypeBase*, which
    > > contains all ever added Types.

    >
    > > I need to be able to do this:

    >
    > > A* myObj = new B();
    > > B->addItems<Type1>(stream1);
    > > B->addItems<Type1>(stream2);
    > > B->addItems<Type2>(stream1);

    >
    > > This is of course impossible, as I need addItems to be virtual,
    > > because myObj must be of type A* (because it is contained in a list of
    > > A*).

    >
    > There seems to be a conflict in semantics. I guess that the definition
    > of A is given by the framework (IOW, you cannot change the "interface"
    > A). This interface states that an object that implements this
    > interface can load and add some items from a stream, and -- this is
    > where I make a wild guess -- the object should be able to determine
    > what to do _solely_ by looking at what the stream contains (there may
    > be some magic numbers in the stream that tell you which data is
    > inside). I further guess that your class B needs additional
    > information about which types have been written into the stream. Is
    > this right?
    >
    > Stuart


    Hi everyone,

    yes, I did mean myObj instead of B, thanks for pointing that out :)

    Now unfortunately the stream does not contain any information on the
    kind of data. Without going into too much detail, think of an image,
    which has many possible features. Each image-object can store a list
    of features in the image (such as faces, edges, objects in general).
    Now to add different types of features to the list, I could make
    functions addFeatureX addFeatureY etc, but since I don't know what
    features are available, I need to have the type of feature as a
    template. Inside the addFeature function I then instantiate (giving
    the image-stream as parameter) the objects of the type of feature,
    which are then added to the list. This is very oversimplified. I do
    not know the number of features that will be added for a specific call
    to the addFeature function. Basically really I would love to just
    "tell" the addFeature function which Object to instantiate. A valid
    solution would be to create a function, which creates an object of a
    specified type and returns it (a factory) and then pass a reference to
    the factory function, which would be called inside addFeature. This I
    want to avoid, as it forces the user of the classes to create such a
    onstructo for every possible feature-class.

    I have done it that way now, but I am still open to suggestions :)

    Thank you and cheers, Jonas
     
    , Apr 22, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page