My problem is this: I have an interface root class with several concrete branch classes. In application code, there exists a vector of pointers to the root class. There are several places where I need to loop over all the elements in the vector and compare them against a given instance:
// Application Code
void compare_loop(Root *r, std::vector<Root*> vec) {
for (auto v : vec) {
if (r->compare(v)) {
// Do something to v
}
}
}
My initial approach was to make "compare" a virtual function in the Root class:
// Class Definition
class Root {
public:
Root(double bar) : Bar(bar) {};
virtual bool compare(Root *r) = 0;
protected:
double Bar;
};
class BranchA : public Root {
public:
BranchA(double bar, double baz) : Root(bar), BazA(baz) {};
bool compare(Root *r) override;
protected:
double BazA;
};
class BranchB : public Root {
public:
BranchB(double bar, int baz, bool foo) : Root(bar), BazB(baz), Foo(foo) {};
bool compare(Root *r) override;
protected:
int BazB;
bool Foo;
};
The issue is that the implementation of the "compare" function should always evaluate to false if the argument is not of the same concrete type, and otherwise depends on the member variables specific to BranchA/BranchB. With a single virtual member function, the only way I could think of implementing this is to attempt a dynamic_cast:
// Implementation
bool BranchA::compare(Root *r) {
BranchA* branch = dynamic_cast<BranchA*>(r);
if (branch == nullptr) {
return false;
}
else {
// Do some complicated comparison based on BranchA members
return (Bar < branch->Bar) && (BazA < branch->BazA);
}
}
bool BranchB::compare(Root *r) {
BranchB* branch = dynamic_cast<BranchB*>(r);
if (branch == nullptr) {
return false;
}
else {
// Do some complicated comparison based on BranchB members
return (Bar > branch->Bar) && (BazB > branch->BazB) && (Foo == branch->Foo);
}
}
This doesn't seem like the most elegant approach to me, but I'm not sure. I would like to know if there is a different approach I could take in the Class Definition and Implementation which would produce the same results without changing the Application Code. Or, is this an instance where the use of dynamic_cast is appropriate?