简体   繁体   中英

C++ How can I combine and add functionality to the same inherited method by a class with multiple inheritance?

So say I have the class empire . empire inherits populationContainer and landContainer as such:

class empire : public populationContainer, public landContainer

Both of those parent classes have the method update() , each of which do their own thing; for example, the pop container calculates pop growth and the land container calculates land expansion.

I currently cannot call empire.update() because it is ambiguous. How do I have both methods get called at once? Additionally, what if I also want empire to have more instructions under update() ?

I can call each method in turn like such:

void empire::update() {
    populationContainer::update();
    landContainer::update();
    // Do other stuff
}

But doesn't this violate the open-closed principal? What if I want to add more 'container' classes with their own update() functions? I'd have to add each one to empire 's update() function.

My solution would be:

// If you add more base classes here, add them also to the 'update' method
class empire : public populationContainer, public landContainer

You need to hold somethere the list of Update functions, for example it may be located in virtual base class IUpdatable that has protected RegisterUpdateFunc(lambda) method and public Update() method that calls to all registered lambdas, one by one.

Now everybody who inherits this class and want to participiate in "update event" just calls once in his constructor

RegisterUpdateFunc([=](){ Update(); })

OO, and in particular the default object model of C++, does not solve all problems.

If you have an object that is product of containers of other kinds of objects, with a set of operations you want to be able to dispatch to each of its parts, the built in C++ object model does not help you much.

There are a few approaches.

First, you can wait for compile time reflection. That is years off.

Second, you can use code generation. Qt uses this with its MOCs.

Third, you can require a central point where the empire class defines what it is a product over:

static auto asProduct(auto&& self){
  return std::forward_as_tuple( get<Base1>(decltype(self)(self), get<Base2>(decltype(self)(self), etc );
}

Third, you can use CRTP to generate the above asProduct from Derived and a list of bases.

Forth, you can generate your Empire class (or a base meta container) with a list of methods to wire up and containers. This is basically writing your own object model.

Fifth, you can just manually forward stuff in update .


In a related issue, is-a seems overused here. Your empire has lands and population. Using is-a here seems awkward. And an abstract object type for a container is also overkill; why not be concrete?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM