Ilonpilaaja
Ilonpilaaja

Reputation: 1249

Abstract class and inheritance

class MyInterface {
public:
    virtual void someFunction()= 0;
};

class X: public MyInterface {
private:
    virtual void doThis() {
        printf("This X");
    }
    virtual void doThat() {
        printf("That X");
    }
public:
    void someFunction() {
        doThis();
        doThat();
    }
};

class Y: public MyInterface, private X {
private:
    void doThat() {
        printf("That Y");
    }
};

MyInterface *iface= new Y();
Y->someFunction();

Coming from Java's flavor of OOP, I am trying to wrap my head around the OOP model of C++. I have read this: http://www.gotw.ca/publications/mill18.htm for suggestions how to design interfaces in C++. The above code is a direct application (or a slight variation thereof) of the rule the author expounds. My question is, is the code above going to produce "This X" followed by "That Y"? What I find confusing is that the author recommends using virtual in conjunction with private. My reasoning is, if a function is private, how are we to override it at all? In the above code, it is granted that Y can be used as the right-hand-side of the assignment, since we derive publicly from the interface. When we call someFunction() on it, since we do not explicitly provide any implementation inside class Y, is it going to use the implementation from class X? Then, provided it does, it looks at doThat() and again uses Ys implementation of it?

Upvotes: 0

Views: 75

Answers (1)

Julo
Julo

Reputation: 1120

The code has a few problems. Here is a working example:

class MyInterface
{
public:
    virtual ~MyInterface() { }
    virtual void someFunction() = 0;
};

class X : public MyInterface
{
private:
    virtual void doThis()
    {
        printf("This X\n");
    }
    virtual void doThat()
    {
        printf("That X\n");
    }

public:
    void someFunction()
    {
        doThis();
        doThat();
    }
};

class Y : public X
{
private:
    void doThat()
    {
        printf("That Y\n");
    }
};

int main()
{
    MyInterface *iface = new Y();
    iface->someFunction();
    delete iface;
}

Explanations

  1. You need to use class Y : public X to be able to use the implementation of void X::someFunction()

    Unfortunately there is no real interface in C++ and there is only a workaround using pure virtual class. This workaround with two parents has it's own limitations (see bellow). And therefore it is also a good idea to add a destructor to interface definition.

    When you use class Y: public MyInterface, private X you need to provide a custom implementation of MyInterface::someFunction(). You have have two parent classes and someFunction() in both parents (X and MyInterface). This is necessary even when there is only one implementation of function. Therefore you need to specify which parent class 'implementation' will be used. Error:

    'Y': cannot instantiate abstract class

    You also get a error when you remove the interface (try to use the interface from X). The reason is simple, when X is private, the implementation is not public and can not be used as a interface.

    'type cast': conversion from 'Y *' to 'MyInterface *' exists, but is inaccessible

  2. You are using class as type in Y->someFunction();

  3. I have no idea, why you can override a private virtual function. I mostly work in C# now and this 'feature' of C++ is something I do not get. You are right, that this should be bad code, but it work (at least in Visual Studio 2017).

    I would also like to know, why this is not considered as error/incorrect code construction.

Upvotes: 1

Related Questions