0

I have an abstract graph (A in the example). And it has inner-class InnerA which is used for one of the functions. I want to derive a new class (e.g. B) from this class and make a wrapper around InnerA to add a new field that should be used in B.

class A {
public:
    class InnerA {};
    virtual void function(InnerA) = 0;
};

class B : public A {
public:
    class InnerB : InnerA {
    public:
        int new_field = 0;
    };
    void function(InnerB b) override {
        b.new_field = 1;
    }
};

But I receive an error that function in B cannot override the base function. What is the right way to implement this?

error: 'void B::function(B::InnerB)' marked 'override', but does not override
     void function(InnerB b) override {
      ^~~~~~~~
  • 1
    You should always put the error message in the question. Anyhow. the functions signatures are different (argument type is different) so it's no override... – JHBonarius Apr 20 '21 at 09:12
  • So there is no possibility to have the same function in the derived class, but with the derived class supplied as the argument? – Alex Teexone Apr 20 '21 at 09:15
  • yes, of course. But it will not be inheritance. E.g. take `A* p = new B();`. You cannot do `p(B{})` as type A doesn't now about B. You can use a normal(overloaded) member function of B. – JHBonarius Apr 20 '21 at 09:18
  • whats the point of having `A` as interface for `B` when `A` doesnt have the right interface? Suppose you didnt get the error then still a function expecting an `InnerA` cannot take a `InnerB` (object slicing). Did you actually mean `virtual void function(InnerA&) = 0;` ? – 463035818_is_not_a_number Apr 20 '21 at 09:18
  • I see, I have an abstract class and must make the implementation of it. But actually, this implementation should work on an extended inner class. So probably I will just create an InnerB out of InnerA and will expect InnerA as the argument. In this case no matter whether InnerA or InnerB is passed, the function will receive and cast it to InnerA. Am I right? – Alex Teexone Apr 20 '21 at 09:24
  • "In this case no matter whether InnerA or InnerB is passed, the function will receive and cast it to InnerA. Am I right?" no. Read about [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) – 463035818_is_not_a_number Apr 20 '21 at 09:32

1 Answers1

1

The argument type is different so this is not a valid override.

Consider this function:

void func(A* a) {
    A::InnerA innerA;
    a->function(innerA);
}

For a valid override, this would have to be a valid call to the derived class function, which it is not. The derived class function must be able to handle all the calls to the base class function, by having the same arguments and return type.

user253751
  • 45,733
  • 5
  • 44
  • 76