【问题标题】:Templates vs Polymorphism模板与多态
【发布时间】:2019-09-24 06:22:42
【问题描述】:

我正在为遗传算法/神经进化编写一个库。目前,该程序使用多态性来允许多种类型的基因组。所以我的代码如下所示:

class Genome { // Interface
    // Some abstract functions 
}

class SpecificGenome : public Genome {
    // implementation
public:   
    int do_something(int x); // Specific behavior, which only this SpecificGenome has
}

class Population {
public:
    Population(size_t population_size, std::function<std::unique_ptr<Genome>()> create_genome);
    // Some functions
    std::vector<std::unique_ptr<Genome>> members;
}

std::unique_ptr<Genome> create_specific_genome(){
    return std::unique_ptr<Genome>(std::make_unique<SpecificGenome>());
}

int main() {
    Population p(150, &create_specific_genome);

    int y = static_cast<SpecificGenome>(*p.members[0].get())->do_something(4);
}

我正在考虑对其进行更改,以便它使用模板而不是多态性,因为每个基因组都编码一个表型,它可以具有任何类型的行为,并且与其他表型类型没有任何共同之处,而且一些基因组使用直接编码方案,不必解码为现象组。因此,每个基因组都必须由用户转换为相应的子类,以暴露其行为,这看起来很丑陋。 问题是基因组的每个子类都是基因组,并且需要有一些特定的功能才能工作,所以多态性非常有意义。

编辑: 现在的问题非常不清楚,所以我想添加一些额外的解释。我希望能够使用任何类型的基因组(NeuralNetwork、NEAT Genome、一个图像……)创建一个群体,所以我使用接口和子类来做到这一点,以便群体中的向量可以使用基因组指针。这很有用,因为每种基因组类型都需要有特定的方法,如交叉和突变。问题出现了,当我想使用特定的功能,比如计算神经网络的输出,基因组解码或获取图像的像素数据时,基因组解码。这让我怀疑使用模板而不是继承是否会更好。

【问题讨论】:

  • @Ron 有。他可以将Genome的不同后代添加到members
  • 那么如果向量中有多种类型的基因组,是否只称为多态性?
  • "poly" 是希腊语中“许多”afaik 的意思。您的代码中没有“很多”。有一个指针不会使它成为多态的
  • @DerEistee 你能提供更多代码吗?好像没有足够的上下文,描述也不是很清楚。
  • 为什么doSomething 不是界面的一部分?即为什么doSomething 不是Genome 的方法?

标签: c++ oop templates polymorphism


【解决方案1】:

模板可能会更好地帮助您的案例,但还有其他含义。

例如,您的列表不能是异质的,它包含的基因组类型。它必须是同一类型。如果您需要异质性,则必须实现某种类型的擦除。

这是一个看起来像您的示例但具有静态多态性的示例:

// no inheritance
class SpecificGenome {
public:   
    int do_something(int x);
}

template<typename G, typename C>
class Population {
public:
    Population(size_t population_size, C create_genome);

    // no need for pointers. Values work just fine.
    std::vector<G> members;
}

// Deduction guide using the create_genome function return type
template<typename C>
Population(std::size_t, C) -> Population<std::invoke_result_t<C>, C>;

SpecificGenome create_specific_genome() {
    return SpecificGenome{};
}

int main() {
    // Uses class template argument deduction
    Population p(150, create_specific_genome);

    int y = p.members[0].do_something(4);
}

顺便说一句,如果您仍然使用std::unique_ptr,您可以使用更好的语法:

std::unique_ptr<Genome> create_specific_genome() {
    // no need for casts
    return std::make_unique<SpecificGenome>();
}

// no need for calls to `get`.
int y = static_cast<SpecificGenome&>(*p.members[0]).do_something(4);

【讨论】:

    猜你喜欢
    • 2019-09-13
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    相关资源
    最近更新 更多