Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is C++ covariance the best solution?

People also ask

Is a high or low covariance better?

A high covariance shows a strong relationship between the two variables, whereas a low covariance shows a weak relationship.

When should covariance be used?

The covariance equation is used to determine the direction of the relationship between two variables–in other words, whether they tend to move in the same or opposite directions. This relationship is determined by the sign (positive or negative) of the covariance value.

How do you know if covariance is significant?

Significance of the formula: Therefore the numerical value of covariance does not have any significance however if it is positive then both variables vary in the same direction else if it is negative then they vary in the opposite direction.

What is a good covariance?

Covariance in Excel: Overview Covariance gives you a positive number if the variables are positively related. You'll get a negative number if they are negatively related. A high covariance basically indicates there is a strong relationship between the variables. A low value means there is a weak relationship.


The canonical example is a .clone()/.copy() method. So you can always do

 obj = obj->copy();

regardless what obj's type is.

Edit: This clone method would be defined in the Object base class (as it actually is in Java). So if clone wasn't covariant, you would either have to cast, or would be restricted to methods of the root base class (which would have only very few methods, compared the class of the source object of the copy).


In general, covariance allows you to express more information in the derived class interface than is true in the base class interface. The behaviour of a derived class is more specific than that of a base class, and covariance expresses (one aspect of) the difference.

It's useful when you have related hierarchies of gubbins, in situations where some clients will want to use a base class interface, but other clients will use the derived class interface. With const-correctness omitted:

class URI { /* stuff */ };

class HttpAddress : public URI {
    bool hasQueryParam(string);
    string &getQueryParam(string);
};

class Resource {
    virtual URI &getIdentifier();
};

class WebPage : public Resource {
    virtual HttpAddress &getIdentifier();
};

Clients which know they have a WebPage (browsers, perhaps) know that it's meaningful to look at query params. Clients which are using the Resource base class know no such thing. They will always bind the returned HttpAddress& to a URI& variable or temporary.

If they suspect, but don't know, that their Resource object has an HttpAddress, then they can dynamic_cast. But covariance is superior to "just knowing" and doing the cast for the same reason that static typing is useful at all.

There are alternatives - stick the getQueryParam function on URI but make hasQueryParam return false for everything (clutters the URI interface). Leave WebPage::getIdentifier defined to return URL&, actually returning an HttpIdentifier&, and have callers do a pointless dynamic_cast (clutters the calling code, and the documentation of WebPage where you say "the URL returned is guaranteed to be dynamically castable to HttpAddress"). Add a getHttpIdentifier function to WebPage (clutters the WebPage interface). Or just use covariance for what it's meant to do, which is express the fact that a WebPage doesn't have an FtpAddress or a MailtoAddress, it has an HttpAddress.

Finally there is of course a reasonable argument that you shouldn't have hierarchies of gubbins, let alone related hierarchies of gubbins. But those classes could just as easily be interfaces with pure virtual methods, so I don't think it affects the validity of using covariance.


I think covariance can be useful when declaring factory methods that return a specific class and not its base class. This article explains this scenario quite well, and includes the following code example:

class product
{
    ...
};

class factory
{
public:
    virtual product *create() const = 0;
    ...
};

class concrete_product : public product
{
    ...
};

class concrete_factory : public factory
{
public:
    virtual concrete_product *create() const
    {
        return new concrete_product;
    }
    ...
};

I often find myself using covariance when working with existing code to get rid of static_casts. Usually the situation is similar to this:

class IPart {};

class IThing {
public:
  virtual IPart* part() = 0;
};

class AFooPart : public IPart {
public:
  void doThis();
};

class AFooThing : public IThing {
  virtual AFooPart* part() {...}
};

class ABarPart : public IPart {
public:
  void doThat();
};

class ABarThing : public IThing {
  virtual ABarPart* part() {...}
};    

This allows me to

AFooThing* pFooThing = ...;
pFooThing->Part()->doThis();

and

ABarThing pBarThing = ...;
pBarThing->Part()->doThat();

instead of

static_cast< AFooPart >(pFooThing->Part())->doThis();

and

static_cast< ABarPart >(pBarThing->Part())->doThat();

Now when coming across such code one could argue about the original design and whether there is a better one – but in my experience there are often constraints such as priorities, cost/benefit etc. which interfere with extensive design beautification and permit only small steps such as this one.