Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overlapping java-like interfaces in C++

I've read on many places that Java's interface can be 100% emulated using C++'s abstract class with all pure virtual methods.

I'm trying to convert this piece of java code:

interface A {
    void a();
}

interface B extends A {
    void b();
}

class C implements A {
    public void a() {
    }
}

class D extends C implements B {
    public void b() {
    }
}

D d = new D();
d.a();
d.b();

into something like this in C++:

class A {
public:
    virtual void a() const = 0;
protected:
    virtual ~A() {
    }
};

class B : public A {
public:
    virtual void b() const = 0;
protected:
    virtual ~B() {
    }
};

class C : public /*implements*/ A {
public:
    virtual void a() const override {
    }
};

class D : public /*extends*/ C, public /*implements*/ B {
public:
    virtual void b() const override {
    }
};

D d;
d.a();
d.b();

but no matter how hard I try, I always end up with C++ complaining about ambiguity and/or missing body definitions.

The idea is that I want to derive from "C" which contains some shared code for all classes (here: "D" but there's more of them) and yet maintain the promise that "D" is 100% interchangeable with any class implementing "B" (incl. the parts from "A").

The errors I'm getting with C++ code above is:

../untitled1/main.cpp: In function ‘int main(int, char**)’:
../untitled1/main.cpp:39:7: error: cannot declare variable ‘d’ to be of abstract type ‘D’
     D d;
       ^
../untitled1/main.cpp:28:7: note:   because the following virtual functions are pure within ‘D’:
 class D : public /*extends*/ C, public /*implements*/ B {
       ^
../untitled1/main.cpp:7:18: note:   virtual void A::a() const
     virtual void a() const = 0;
                  ^
../untitled1/main.cpp:40:7: error: request for member ‘a’ is ambiguous
     d.a();
       ^
../untitled1/main.cpp:7:18: note: candidates are: virtual void A::a() const
     virtual void a() const = 0;
                  ^
../untitled1/main.cpp:23:18: note:                 virtual void C::a() const
     virtual void a() const override {
                  ^
like image 330
Miro Kropacek Avatar asked Jul 04 '17 07:07

Miro Kropacek


People also ask

Does C++ have interfaces like Java?

In C++ programming there is no built-in concept of interfaces. In order to create an interface, we need to create an abstract class which is having only pure virtual methods.

Can an interface have multiple methods?

Unless the class that implements the interface is abstract, all the methods of the interface need to be defined in the class. An interface can contain any number of methods.

Is it possible a Java class can implement any no of interfaces simultaneously justify with an example?

Yes, it is possible. This is the catch: java does not support multiple inheritance, i.e. class cannot extend more than one class. However class can implement multiple interfaces.

How do we solve the problem of adding a new method in an interface without breaking all the child classes that implement the interface?

If the module containing the interface is compiled at a different time than the module containing the implementation, you can add a new method to the interface without it being aware that it's breaking an external module.


1 Answers

This is a problem that is solved by virtual inheritance from A.

class A {
public:
    virtual void a() const = 0;
protected:
    virtual ~A() {
    }
};

class B : public virtual A {
public:
    virtual void b() const = 0;
protected:
    virtual ~B() {
    }
};

class C : public virtual A {
public:
    virtual void a() const override {
    }
};

class D : public C, public  B {
public:
    virtual void b() const override {
    }
};

The problem is that unless you specify that both C and B need to share an A sub-object (all derived classes contain their bases as sub-objects), the two sub-objects you get from inheriting both B and C will be unrelated.

In your original scheme, the implementation provided by C to the pure virtual member in A wasn't considered as an implementation for the same function required by the A in B.

Since now there is only one A sub-object, this problem goes away. But note that virtual inheritance is not without a price. So think if you really want to go with such a design.

like image 180
StoryTeller - Unslander Monica Avatar answered Sep 20 '22 15:09

StoryTeller - Unslander Monica