【问题标题】:How can I copy a templated instance with a virtual base class? [duplicate]如何复制具有虚拟基类的模板化实例? [复制]
【发布时间】:2021-02-08 08:12:25
【问题描述】:

TL;DR
鉴于该元素是模板类的一个实例,它也是从虚拟基类派生的,我如何复制向量的最后一个元素?


我想创建一个向量作为撤消堆栈。堆栈应保存基于浮点和字符串的对象(可能还有其他类型)。它可能包含所有浮点数、所有字符串或两者的组合。 第一次添加浮点数或字符串时,我想将它的副本添加到堆栈中。

这是我目前所拥有的:

class Base
{
...
virtual bool func1() = 0;
}

带有模板参数的派生类

template<typename T>
class derived : public base {...}

还有这两个

class foo : public derived<float>
class bar : public derived<string>

主要:

std::vector<Base> stack;
if (condition) 
stack.push_back(new foo())
else
stack.push_back(new bar())

如果stack.back().func1()==true 添加另一个foobarfunc1foobar 中实现,如果它是堆栈中的第一个 foobar,则返回 true

if (stack.back().func1())  
 //do something like
 //stack.push_back(new foo) if stack.back() is a foo
 //stack.push_back(new bar) if stack.back() is a bar

现在,我不能做stack.push_back(new Base),因为它有一个虚函数。出于同样的原因,我无法复制stack.back()。 我也不能做stack.push_back(new drived&lt;T&gt;),因为我不知道T 是。 我绝对不想硬编码new foonew barstringfloat,因为我想为将来的派生类保留通用代码。

既然这个元素是从虚拟基类派生的模板类,我该如何复制向量的最后一个元素,或者添加一个相同类型的新元素?

【问题讨论】:

  • 您必须使用std::vector&lt;Base*&gt; 或更好的std::vector&lt;std::unique_ptr&lt;Base&gt;&gt; 才能使用。通常这个问题可以通过创建一个每个派生类都可以覆盖的虚拟clone 方法来解决。
  • 通过中间类的模板化和间接化没有区别 - 您解决这个问题的方式与直接从 Base 继承的 foobar 完全相同。
  • 谢谢@super,这是我一直在寻找的解决方案。

标签: c++ templates


【解决方案1】:

传统上,它是通过将clone 方法添加到Base 来完成的:

struct Base {
    virtual std::unique_ptr<Base> clone() const = 0;
    virtual ~Base() = default;
};

CRTP 可用于在此处自动覆盖此方法:

template<class Child> struct Clonable: Base {
    std::unique_ptr<Base> clone() const final {
        auto &asChild = *static_cast<Child const *>(this);
        return std::make_unique<Child>(asChild);
    }
};

struct Foo: Clonable<Foo> {};

【讨论】:

  • @TedLyngmo 是的,谢谢,错过了。
猜你喜欢
  • 2014-12-11
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
  • 2015-04-18
  • 1970-01-01
  • 2012-05-04
相关资源
最近更新 更多