I tried to implement some interfaces and their children. This is my idea:
Interface
/ \
Interface2 InterfaceDefination
| /
Interface2Defination
And this is my code:
#include <iostream>
class Interface {
public:
virtual void method1() = 0;
virtual void print() = 0;
};
class Interface2 : public Interface {
public:
virtual void method2() = 0;
};
class InterfaceDefination : public Interface {
public:
virtual void method1() override {
std::cout << "method1 from InterfaceDefination\n";
}
};
class Interface2Defination : public Interface2, public InterfaceDefination {
public:
using InterfaceDefination::method1;
virtual void print() override {
std::cout << "print from Interface2Defination\n";
}
virtual void method2() override {
std::cout << "method2 from Interface2Defination\n";
}
};
int main() {
Interface2Defination c;
c.method1();
c.method2();
c.print();
}
My expected output is:
method1 from InterfaceDefination
method2 from Interface2Defination
print from Interface2Defination
But accidentally i received these errors:
main.cpp:33:24: error: variable type 'Interface2Defination' is an abstract class
Interface2Defination c;
^
main.cpp:5:16: note: unimplemented pure virtual method 'method1' in 'Interface2Defination'
virtual void method1() = 0;
^
1 error generated.
make: *** [<builtin>: main.o] Error 1
exit status 2
https://godbolt.org/z/9ncoGfn4P
In this case, the error means using
keyword is not making method method1
usable in class Interface2Defination
. What should i do with it?
A using
declaration is a declaration. It is not a definition. It does not define anything "new". What it does is declare: ok, I have a symbol X, but it really refers to X in my parent class (for this version of a using
declaration).
You might ask what's the point, aren't you inheriting X from your parent class in the normal fashion. Yes, that's true, but it's not the same thing, but the technical differences are mostly immaterial here.
What's also important here is that the shown diagram is misleading. It is a popular way to portray (non-virtual) diamond inheritance, but every time it's shown, it is 100% wrong. This is because Interface2Defination
does not inherit one instance of Interface
, but two. This is a more accurate inheritance diagram:
Interface Interface
| |
Interface2 InterfaceDefination
| /
Interface2Defination
For each one of the two instances of Interface
parent classes, only one of its abstract methods gets defined and overridden, hence the shown code is ill-formed.
The using
declaration does not define the imported method in the child class, and formally override it. A using
declaration does not "count" for the purpose of overriding an abstract method. Only formally defining an inherited abstract method does that, not declaring one.