Some misc C++ questions (multimap, derived class function argument,virtual static)

Discussion in 'C++' started by Digital Puer, Sep 13, 2009.

  1. Digital Puer

    Digital Puer Guest

    I have several C++ questions:

    1. Why are the interfaces for multiset and multimap so complicated for
    getting multiple values?

    Instead of
    multimap<Key, Value>

    I usually prefer
    map<Key, vector<Value> >

    Isn't that much easier to use?


    2. Suppose I have a base class that looks like:

    class Base
    {
    public:
    virtual void combine(const Base &other, Base &result) = 0;
    }

    class Derived : public Base
    {
    private:
    string _name;
    public:
    void combine(const Derived &other, Derived &other) {}
    }

    When I try to instantiate Derived, g++ is telling me that the
    pure virtual method Base.combine() is not implemented.
    Why does Derived.combine() above not override Base.combine()?

    Instead, I have to do some casting, like:

    void combine(const Base &other, Base &result)
    {
    Derived &a = (Derived &)other;
    string combination = _name + a._name;

    ((Derived &)result)._name = combination;
    }

    Is there a better approach?


    3. For my abstract Base class, I want to specify a static "Factory"
    method that produces a Base*:

    class Base
    {
    virtual static Base* createRandomInstance();
    }

    I want to force all my Derived classes to provide such a factory
    method that produces a Derived *.

    However, apparently I cannot have a virtual static method
    in C++ (or in Java). What is the best way to force that all
    derived classes have such a factory method?
     
    Digital Puer, Sep 13, 2009
    #1
    1. Advertising

  2. * Digital Puer:
    > I have several C++ questions:
    >
    > 1. Why are the interfaces for multiset and multimap so complicated for
    > getting multiple values?
    >
    > Instead of
    > multimap<Key, Value>
    >
    > I usually prefer
    > map<Key, vector<Value> >
    >
    > Isn't that much easier to use?


    No opinion.


    > 2. Suppose I have a base class that looks like:
    >
    > class Base
    > {
    > public:
    > virtual void combine(const Base &other, Base &result) = 0;
    > }
    >
    > class Derived : public Base
    > {
    > private:
    > string _name;
    > public:
    > void combine(const Derived &other, Derived &other) {}
    > }
    >
    > When I try to instantiate Derived, g++ is telling me that the
    > pure virtual method Base.combine() is not implemented.
    > Why does Derived.combine() above not override Base.combine()?


    Read up on the Liskov Substitution Principle.

    Essentially if you could override that way you could then do

    Derived d;
    Base b;
    Base& r = d;

    r.combine( b, b );

    where the Derived object gets Base objects in as arguments, but expects Derived
    ones.


    > Instead, I have to do some casting, like:
    >
    > void combine(const Base &other, Base &result)
    > {
    > Derived &a = (Derived &)other;
    > string combination = _name + a._name;
    >
    > ((Derived &)result)._name = combination;
    > }
    >
    > Is there a better approach?


    Don't cast.

    E.g. you might add virtual member routines that give access to the name.


    > 3. For my abstract Base class, I want to specify a static "Factory"
    > method that produces a Base*:
    >
    > class Base
    > {
    > virtual static Base* createRandomInstance();
    > }
    >
    > I want to force all my Derived classes to provide such a factory
    > method that produces a Derived *.
    >
    > However, apparently I cannot have a virtual static method
    > in C++ (or in Java). What is the best way to force that all
    > derived classes have such a factory method?


    Why not implement a generic factory that works for nearly all derived classes?

    Like

    template< class T >
    T* createRandomInstance() { return new T(); }


    class Derived: public Base
    {
    public:
    Derived( char const [] ) {}
    };

    template<>
    Derived* createRandomInstance<Derived>() { return new Derived(""); }


    Base* p = createRandomInstance<Base>();

    If the generic version works for a derived class, fine. If not, then using it
    for a derived class probably won't compile. So then you've "forced" the derived
    class to provide a specialization.


    Cheers & hth.,

    - Alf
     
    Alf P. Steinbach, Sep 13, 2009
    #2
    1. Advertising

  3. Digital Puer

    Francesco Guest

    Re: Some misc C++ questions (multimap, derived class functionargument, virtual static)

    On 13 Set, 21:10, Digital Puer <> wrote:
    > I have several C++ questions:
    >
    > 1. Why are the interfaces for multiset and multimap so complicated for
    > getting multiple values?


    I don't find them that convolute... what is the part of the interface
    that you don't like?

    > Instead of
    > multimap<Key, Value>
    >
    > I usually prefer
    > map<Key, vector<Value> >
    >
    > Isn't that much easier to use?


    The two containers above are very similar but not interchangeable.

    A multimap has its advantages on map, in this specific case. It allows
    you to store separately two physically different keys which are just
    logically equal to each other. If you don't need this peculiarity and
    map fulfills your needs, you're perfectly fine using it.

    Just my two cents, sorry for the other points but I should understand
    them better before posting anything about them.

    Cheers,
    Francesco
     
    Francesco, Sep 13, 2009
    #3
  4. Digital Puer

    Digital Puer Guest

    Re: Some misc C++ questions (multimap, derived class functionargument, virtual static)

    On Sep 13, 12:37 pm, Pete Becker <> wrote:
    > Digital Puer wrote:
    > > However, apparently I cannot have a virtual static method
    > > in C++ (or in Java). What is the best way to force that all
    > > derived classes have such a factory method?

    >
    > Specification and testing. Beyond that, why do you care? If someone
    > wants to derived from your class but not provide a factory, what harm
    > does it do?
    >



    Because I want to enforce the existence of a factory method
    in all derived classes. Every derived class will have its own
    data, and I want the class to be able to produce a Base *
    though the factory. I would like this factory method to be
    usable by a consumer of the Base class:

    void consumer()
    {
    Base *randomItem = Derived::createInstance(); // factory
    doSomething(randomItem);
    }

    You are right that I could write an English specification that
    says that all derived classes must have a factory method,
    but I want to have that enforced in the Base class.

    I guess a better approach would be to move the factory method
    into another class that knows about the Derived class.

    void consumer(Factory &factory)
    {
    Base *randomItem = factory.createInstanceOfDerived();
    doSomething(randomItem);
    }
     
    Digital Puer, Sep 13, 2009
    #4
  5. Digital Puer

    Paul N Guest

    Re: Some misc C++ questions (multimap, derived class functionargument, virtual static)

    On 13 Sep, 20:10, Digital Puer <> wrote:

    > However, apparently I cannot have a virtual static method
    > in C++ (or in Java).


    I asked a similar question on 21 Mar 2008 - you can find it if you put
    "gw7rib virtual static" into Google Groups and click "Search Groups".
    Marcel Müller provided a solution to the problem I was having.

    Hope this helps.
    Paul.
     
    Paul N, Sep 14, 2009
    #5
  6. Re: Some misc C++ questions (multimap, derived class functionargument, virtual static)

    On Sep 13, 12:10 pm, Digital Puer <> wrote:
    > However, apparently I cannot have a virtual static method
    > in C++ (or in Java).


    What would a "virtual static method" do?

    Ex:

    struct base { virtual void foo(); };
    struct derived : base { virtual void foo(); };
    int main()
    {
    derived d;
    d.foo(); //calls derived::foo
    derived* pd = &d;
    pd->foo(); //calls derived::foo
    base* pb = pd;
    pb->foo(); //calls derived::foo

    base b;
    b.foo(); //calls base::foo
    base* pb2 = &b;
    pb2->foo(); //calls base::foo
    }

    In this example, which foo function is called depends upon the most-
    derived type of the "this" object. If the most most-derived type of
    the "this" object is "derived", then "derived::foo" is called. If the
    most-derived type of the "this" object is "base", then "base::foo" is
    called. Virtual functions require a "this" object. Static functions
    forbid a "this" object. Thus it's not obvious what the semantics would
    be for a "virtual static" function.
     
    Joshua Maurice, Sep 14, 2009
    #6
    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