Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Consider following code sample

#include <iostream>
using namespace std;

class Color
{
public:
    virtual void mixColors(Color &anotherColor) = 0;
};

class RGB : public Color
{
public:
    void mixColors(RGB &anotherColor);
};

void RGB::mixColors(RGB &kol)
{
    return RGB(0xABCDEF);
}

I perfectly know why this code is not working (mixColors() in RGB is not implementing pure virtual function, because it has different set of arguments). However I would like to ask if is there another approach to solve this problem. Let's say I would like to mix colors, but using different algorithm for different color classes. I would appreciate any help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
381 views
Welcome To Ask or Share your Answers For Others

1 Answer

In a language where inheritance entails subtyping, such as C++, you cannot make a member function argument "more specific" in a derived class. (At least not without breaking type safety.) For a full technical explanation, see here.

To understand this in more concrete terms, notice that, in your Color class, you are asserting the existence of a member function with signature:

virtual void mixColors(Color &anotherColor) = 0;

This means that any color can be mixed with any other color (not necessarily of the same class), and that the concrete implementation of this mixing procedure only depends on the class of the first color. Which is just plain wrong.

The simplest solution to your probem is to simply use function overloading:

// I am assuming RGB and CMYK are cheap to pass by value, which seems reasonable.
// If this is not true, you can always pass them by const reference.

RGB mix_colors(RGB rgb1, RGB rgb2) { ... }

CMYK mix_colors(CMYK cmyk1, CMYK cmyk2) { ... }

Or, assuming you really want to mutate one of the colors, instead of producing a new color object:

class RGB
{
    // ...
public:
    RGB & mix_colors(RGB);  // return *this at the end
};

class CMYK
{
    // ...
public:
    CMYK & mix_colors(CMYK);  // return *this at the end
};

There is a downside to using overloading instead of virtual member functions, however: overloads must be resolved at compile time, while virtual member functions can be dynamically dispatched. Sadly, if you need to perform runtime dispatch on the colors you want to mix, you are kind of screwed, because C++ has nothing like Haskell's type classes or Common Lisp's multimethods. You can encode multiple dispatch using the visitor pattern, but this is decidedly not pretty.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...