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?
CodePudding user response:
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;
}