Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve which function is called based on the type of objects in a container?

I have some basic inheritance trees:

class Base {
    virtual double func() = 0;
    // functionality is not important for the problem
    // but it's good to know that Base has some virtual functions
};
class DerivedA : public Base {
    virtual double func() {}; // implementation A
};
class DerivedB : public Base {
    virtual double func() {}; // implementation B
};

I have a container holding a pointer to either DerivedA or DerivedB instances.

void f1(std::vector<Base*> a) () { /* some code */ }

int main(in, char**) {
  std::vector<Base*> base_container;
  f1(base_container); // works fine
}

Almost everything works on Base, but I have some function, not specified in DerivedA or DerivedB, that is implementation specific, but works on a DerivedA or DerivedB container. Let's assume the following code snippet:

void f2(std::vector<DerivedA*> a) () { /* implementation A specific code */ }
void f2(std::vector<DerivedB*> a) () { /* implementation B specific code */ }

What is the best practise to call the correct function? I list some possible solutions, which came to my mind, but they all have major drawbacks.

  1. I could hold all data in implementation specific containers. However, f1() won't work anymore since std::vector<DerivedA*> is not a child of std::vector<Base*> (for good reasons!).

  2. I could manually cast all objects all the time, but that is ugly.

  3. I could manually call the correct function that expects a Base container by giving them distinctive name (like f2_a and f2_b), but that seems ugly.

  4. I could implement f2 as a function template specialization, but that seems abusive.

  5. I could try to make the function on the container depend only on functions of the objects in the container and then implement overloaded functions for them. This is a good solution in several cases, but in my case it really is a function on the container, giving different implementations on the container for DerivedA and DerivedB, not just iterating over the contents of the container.

How would you implement such thing? How can I get a Container that is able to be passed to both f1() and f2()?

like image 442
hildensia Avatar asked Oct 03 '22 21:10

hildensia


1 Answers

The best solution is to have your inheritance represent substitution and have the base class have a fully-formed interface that does all the work, using virtual methods to pick which derived class methods to use. Then f2 just takes a vector of base pointers.

Otherwise, if there really are specifically different interfaces in the derived classes that you need to access (and if there are, take one moment to think about what you did with your design), your best appoach is differently named methods, one for each derived type, each of which accepts a vector of base pointers. With appropriately named methods it will be clear to the user which type is expected.

like image 106
Mark B Avatar answered Oct 07 '22 21:10

Mark B