I'm working on a physics project simulation where I need to calculate the potential of 2 molecules.
and this is part of the code that I thought to write:
class Molecule
{
public:
double someBulshit;
virutal double Potential(const Molecule & mol);
}
class LC : public Molecule
{
public:
virtual double Potential(const Molecule & mol)
{
if(typeid(mol) ==typeid(LC))
return 1;// for the example
return 3;
}
}
class Col : public Molecule
{
public:
virtual double Potential(Molecule mol)
{
if (typeid(mol) == typeid(Col))
return 2;
return 3;
}
}
int main(int argc, char* argv[])
{
Molecule mol1 = new Col();
Molecule mol2 = new LC();
double my_potential = mol1.Potential(mol2);
printf ("%f",my_potential);
}
I heard that using typeid is bad, but I cant find another way to do so without using it. This is also performance sensitive and typeid I understood that typeid is not recommended with it.
I tried to split to different functions:
double Potential(const LC & mol);
double Potential(const Col & mol);
But then I cant call them polymorphic..
You need some kind of double dispatch. The usual recommendation here is the Visitor Pattern. However, I don't recommend it in this case.
I think, that you should keep the Molecule base, and the derived classes. You should add an ID into the Molecule class. And implement double dispatch with a 2D table, indexed by the 2 objects' ID. Like this:
class Molecule {
private:
int m_id;
public:
Molecule(int id) : m_id(id) { }
int id() const {
return m_id;
}
};
class LC: public Molecule {
private:
// members here
public:
LC() : Molecule(0) { }
};
class Col: public Molecule {
private:
// members here
public:
Col() : Molecule(1) { }
};
double potential_lc_vs_lc(const Molecule &a, const Molecule &b) {
const LC &lc_a = static_cast<LC &>(a);
const LC &lc_b = static_cast<LC &>(b);
// calculate potential LC (lc_a) vs LC (lc_b) here
return ...;
}
// all the potential_XX_vs_XX functions come here
const double (*potentialCalculatorTable[2][2])(const Molecule &, const Molecule &) = { { potential_lc_vs_lc, potential_lc_vs_col }, ... };
double calculatePotential(const Molecule &a, const Molecule &b) {
return (*potentialCalculatorTable[a.id()][b.id()])(a, b);
}
This needs some manual management, but the solution is clear (in my opinion), and fast.