I've coded a crossover method for a genetic algorithm (see https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)).
The crossover method modifies the private members of the Chromosome class but I pulled it out of Chromosome into a separate pure virtual base class CrossoverStrategy (friend of Chromosome) to keep each crossover method nicely encapsulated in a subclass, i.e. the GoF strategy pattern (see https://en.wikipedia.org/wiki/Strategy_pattern).
Nw the problem is CrossoverStrategy subclasses can't access Chromosome private members because friendship isn't inherited in C++. The only 2 solutions I see are:
1) Add accessor methods to the pure virtual base class e.g. CrossoverStrategy::getGenes() to make Chromosome private members accessible to subclasses. Because CrossoverStrategy can't anticipate all the stuff its subclasses may want to do with Chromosome, I need to expose everything up front. Ugly!
2) Forward declare each CrossoverStrategy subclass and explicitly make it a friend of Chromosome. This feels slightly less ugly, at least keeps the interfaces and code cleaner. I'm leaning towards this option for aesthetics.
Any better design suggestions? Code below.
// Chromosome.h ++++++++++++++++++++++++++++++++++++++++++++++++
class CrossoverStrategy
{
public:
virtual std::vector<Chromosome*> crossover(Chromosome *parent1, Chromosome *parent2);
const std::vector<double> &getGenes(Chromosome *instance) { return instance != NULL ? instance->m_genes : std::vector<double>(); }; // OPTION #1 ... BOO! UGLY!
};
class CrossoverStrategyExample1; // OPTION #2 ... BOO! UGLY!
class Chromosome
{
public:
// Friends
friend class CrossoverStrategy;
friend class CrossoverStrategyExample1; // OPTION #2 ... BOO! UGLY!
private:
std::vector<double> m_genes;
};
// CrossoverStrategies.h ++++++++++++++++++++++++++++++++++++++++++++++++
#include "Chromosome.h"
class CrossoverStrategyExample1 : public CrossoverStrategy
{
public:
virtual std::vector<Chromosome*> crossover(Chromosome *parent1, Chromosome *parent2);
private:
};
// CrossoverStrategies.cpp ++++++++++++++++++++++++++++++++++++++++++++++++
#include "CrossoverStrategies.h"
std::vector<Chromosome*> CrossoverStrategyExample1::crossover(Chromosome *parent1, Chromosome *parent2)
{
// Do something with Chromosome private members
// PROBLEM ... m_genes not accessible to subclasses? BOO BOO BOO!
(for unsigned long i = 0; i < parent1->m_genes.size(); i++)
parent1->m_genes[i] = 0.0;
}
Aucun commentaire:
Enregistrer un commentaire