Re: Some misc C++ questions (multimap, derived class function
argument, virtual static)
This is a MIME GnuPG-signed message. If you see this text, it means that
your E-mail or Usenet software does not support MIME signed messages.
The Internet standard for MIME PGP messages, RFC 2015, was published in 1996.
To open this message correctly you will need to install E-mail or Usenet
software that supports modern Internet standards.
--=_mimegpg-commodore.email-scan.com-2936-1252867771-0001
Content-Type: text/plain; format=flowed; charset="US-ASCII"
Content-Disposition: inline
Content-Transfer-Encoding: 7bit
Digital Puer writes:
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?
Maybe, but adding elements to a vector may require a time-consuming copy of
all existing elements, in order to grow a vector to accomodate the new
element. Furthermore, multimap's methods are nearly identical to map's,
making it possible to implement other templates that can use either
container. That's not possible with your alternative, which requires a
completely different approach for using the contents of your map.
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()?
Because it's a different method.
void combine(const Base &other, Base &result)
and
void combine(const Derived &other, Derived &other)
are two different methods, with differents signatures. In order for one to
override the other, the signatures must be identical.
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?
Yes, but only in a sense that you should use dynamic_cast to verify that
both of your parameters are indeed instances of Derived. Otherwise, if your
method receives an actual instance of Base, hilarity ensues. Using
dynamic_cast enables to verify your input parameters, and take some
meaningful action otherwise.
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?
Well, the best way I can think of is to define your base class as a
template:
template<typename Derived> class Base {
public:
static Derived *createRandomInstance();
};
Your derived classes would be defined as follows:
class Derived : public Base<Derived> {
};
--=_mimegpg-commodore.email-scan.com-2936-1252867771-0001
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
iEYEABECAAYFAkqtPrsACgkQx9p3GYHlUOJySACfYywLQIE9NoRfNGjr+SmIOSVX
hUQAnRTUzYXe0L2E5agArUiru5VuYxr6
=/vwW
-----END PGP SIGNATURE-----
--=_mimegpg-commodore.email-scan.com-2936-1252867771-0001--