【发布时间】:2019-05-29 15:21:35
【问题描述】:
我为遗传算法编写了一个交叉方法(请参阅https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm))。
交叉方法修改了 Chromosome 类的私有成员,但我将其从 Chromosome 中拉出到单独的纯虚拟基类 CrossoverStrategy(Chromosome 的朋友)中,以使每个交叉方法很好地封装在子类中,即 GoF 策略模式(见https://en.wikipedia.org/wiki/Strategy_pattern)。
现在的问题是 CrossoverStrategy 子类无法访问 Chromosome 私有成员,因为 C++ 中没有继承友谊。我看到的唯一 2 个解决方案是:
1) 将访问器方法添加到纯虚拟基类,例如CrossoverStrategy::getGenes() 使子类可以访问 Chromosome 私有成员。因为 CrossoverStrategy 无法预测其子类可能想要对 Chromosome 做的所有事情,所以我需要预先公开所有内容。丑!
2) 前向声明每个 CrossoverStrategy 子类并明确使其成为 Chromosome 的朋友。这感觉不那么难看,至少保持接口和代码更干净。为了美观,我倾向于这个选项。
有更好的设计建议吗?代码如下。
// Chromosome.h ++++++++++++++++++++++++++++++++++++++++++++++++
class CrossoverStrategy
{
public:
virtual std::vector<Chromosome*> crossover(Chromosome *parent1, Chromosome *parent2) = 0;
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;
}
【问题讨论】:
-
不仅丑陋,而且致命。您不应返回对局部变量的引用。
-
鲍勃是你的朋友。你把你的秘密托付给他。但是鲍勃的儿子格里夫(Griff)的毒品交易垃圾袋呢?你会因为信任 Bob 而自动信任 Griff 吗?没有。如果派生自
friends 的类自动成为friends,那么您可以将任何您想要的子类化并完全覆盖封装。不是一个好计划。 -
如果您不可能为指针传递空指针,请考虑通过引用而不是指针传递。几乎消除了整个家庭的意外搞砸。
-
鉴于您希望多个类/函数能够访问构成
Chromosome的数据,为什么不是数据public? -
@Peter 因为那时 任何人 都可以访问私人数据。如果只有朋友(及其子类)可以访问,我会更喜欢。这是一个不错的选择 3,但风险是我们完全解开 Chromosome。
标签: c++ inheritance design-patterns friend