Home > Blockchain >  Why can't I use `using` in a multiple inheritance c ?
Why can't I use `using` in a multiple inheritance c ?

Time:02-08

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?

CodePudding user response:

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.

CodePudding user response:

As it stands, there are two Interface::method1s in Interface2Defination, and only one of them has an implementation. If you virtually inherit Interface, you have one, with a definition.

#include <iostream>

class Interface {
public:
  virtual void method1() = 0;
  virtual void print() = 0;
};

class Interface2 : public virtual Interface {
public:
  virtual void method2() = 0;
};

class InterfaceDefination : public virtual Interface {
public:
  virtual void method1() override {
    std::cout << "method1 from InterfaceDefination\n";
  }
};

class Interface2Defination : public Interface2, public InterfaceDefination {
public:
  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();
}
  •  Tags:  
  • Related