Search code examples
c++nestedoverriding

C++ override of nested class function


I have a class that derives from a base class, which has a nested class. I want to override a nested class's member function in my derived class and override a base class's member function. (as shown below)

I found a solution (https://stackoverflow.com/a/11448927/13147242) that works by creating another nested class that inherits from the base class's nested class. But when creating an instance of this new nested class I get another return type, which doesn't help me because the function that I want to override that returns a base's nested class object, but should access the nested's override function.

A code example of that setup looks like this:


class Base {
public:
  class Nested {
    friend class Derived;

  public:
    virtual void funcNested() { std::cout << "funcNested()" << std::endl; }
  };

  virtual Nested funcBase() {
    std::cout << "funcBase()" << std::endl;
    Nested tmp;
    tmp.funcNested();
    return tmp;
  }
};

class Derived : public Base {
public:
  // I want to override this function without creating another nested class that derives from Nested, i.e.
  // void Base::Nested::funcNested() override { /* ... */ }

  // the mentioned solution does it like this:
  class DerivedNested : public Base::Nested {
  public:
    void funcNested() override { std::cout << "override funcNested()" << std::endl; }
  };

  // but then I can't override this function in a way that the nested function is called
  Nested funcBase() override {
    std::cout << "override funcBase()" << std::endl;
    return DerivedNested();
  }
};


int main() {
  Derived derived;
  Base::Nested nested = derived.funcBase();
  nested.funcNested();

  return 0;
}

Then the output here is:

override funcBase()
funcNested()

but I want to have:

override funcBase()
override funcNested()

Is this possible?


Solution

  • It appears the issue is that in this line Base::Nested nested = derived.funcBase(); a copy of type Nested is created by a Nested::Nested(Nested&) copy constructor, out of derived object (DerivedNested). Then in nested.funcNested(); line a method is called on that copy object of parent class, thus no dynamic dispatch here.

    As described in this answer of the similar question, you should use reference/smart pointer to prevent creating a copy of the base class. Like:

    #include <memory>
    
    class Base {
    public:
      class Nested {
        friend class Derived;
    
      public:
        virtual void funcNested() { std::cout << "funcNested()" << std::endl; }
      };
    
      virtual std::shared_ptr<Nested> funcBase() {
        std::cout << "funcBase()" << std::endl;
        Nested tmp;
        tmp.funcNested();
        return std::make_shared<Nested>(tmp);
      }
    };
    
    class Derived : public Base {
    public:
      class DerivedNested : public Base::Nested {
      public:
        virtual void funcNested() override { std::cout << "override funcNested()" << std::endl; }
      };
    
      std::shared_ptr<Nested> funcBase() override {
        std::cout << "override funcBase()" << std::endl;
        DerivedNested tmp;
        tmp.funcNested();
        return std::make_shared<DerivedNested>(tmp);
      }
    };
    
    int main() {
        Derived derived; 
        auto nested = derived.funcBase(); 
        nested->funcNested();
    
        return 0;
    }