【问题标题】:Holding Template Class Objects in Array在数组中保存模板类对象
【发布时间】:2015-11-03 19:43:46
【问题描述】:

我必须为我的项目在一个数组中保存不同类型的数据。我创建了一个用于生成对象的模板类。

template<class Queue>
class Template  {

public:
    Queue value;
    Template(Queue input) {
        value = input;
    }

};

但我不能在不使用抽象类的情况下将它们保存在一个数组中。我为此创建了一个 void 指针数组。我喜欢它;

void *array[21];
array[index] = new Template<int>(number);
array[index] = new Template<string>(text);

没有抽象类有没有可能的解决方案?我的意思是,我可以在模板类的数组中保存这个模板对象吗?

【问题讨论】:

  • 您可能误解了模板参数。 int 实际上如何代表Queue
  • 不,我将在队列实现中使用不同类型的数据。因为这个,我给它命名了。
  • 您可能需要一些中间模板类,例如template &lt;class T&gt; class Queue;,其中T 分别实例化为intstd::string
  • 您介意我问您为什么删除了该代码 sn-p 吗?您正在删除其他读者理解人们答案的必要上下文。

标签: c++ arrays templates


【解决方案1】:

创建层次结构并利用动态绑定:

class Base  {
public:
  virtual ~Base() {};
  // ...
};

template<class Queue>
class Template : public Base {
    Queue value;
public:
    Template(Queue const &input) :value(input) {}
    // ...
};

并将其用作:

Base *array[21];
array[index] = new Template<int>(number);
array[index + 1] = new Template<string>(text);

此外,不要使用原始数组和原始指针,而是使用 STL 工具,例如 std::array 智能指针(例如,std::shared_ptr&lt;Base&gt;std::unique_ptr&lt;Base&gt;):

std::array<std::unique_ptr<Base>, 21> arr;
arr[index].reset(new Template<int>(number));
arr[index + 1].reset(new Template<string>(text));

也更喜欢将成员变量初始化到构造函数的初始化列表而不是它的主体。

【讨论】:

  • 好答案。还要注意,如果他需要该值,他可以在 Base 中拥有一个虚函数并在 Template 中覆盖它,利用协变返回类型!
  • @Moo-Juice 协变返回类型很棒,但不适用于他的 intstd::string 示例。这里的基类允许将这些值存储在一个统一的数组中,但我仍然想知道他为什么需要这个。事实上,他每次想要取回数据时都必须dynamic_cast
  • @NathanOliver,实际上这不是真的。你可以覆盖一个虚函数并提供一个不同的返回类型,只要它是协变的。然而,正如 GuyGreer 指出的那样,它不适合这种情况。
  • @Moo-Juice 啊我明白了。谢谢。
  • 可能值得将虚拟析构函数显式添加到Base,以防 OP 不知道他需要它。
【解决方案2】:

这通常表明您应该在更高级别重新考虑您的代码结构,以便您根本不需要它。

否则,我看到您有四个选择(如果算上上面的“不要这样做”,则为五个):

  1. 使用可以保存所有数据类型的统一类型(例如 std::string 并在需要时解析出数字信息)。该功能可以封装在一个类中,该类提供成员函数以简化此操作。

  2. 使用boost::variant,如果您是 C++ 新手,那么我不建议您立即解决此类问题。

  3. 使用 101010 解释的基类。我要补充一点,您可能希望在基类中使用枚举来告诉您存储的数据类型

  4. 使用boost::any,这比变体更难使用,尽管它更容易理解。

如果没有更多关于您想要实现的目标的信息,我们真的无法就如何进行提供任何更好的指导。

【讨论】:

  • @jesta 这些命令除了“放置”之外还能做什么?他们把它们放在哪里?您需要知道多少关于您放置在某处的类型是什么?
  • @jesta,根据你的说法,我推荐解决方案 1。
【解决方案3】:

我会使用变体类型。你可以推出你的own,但更喜欢使用boost::variant

#include <boost/variant.hpp>
#include <iostream>
#include <string>

using namespace std;

template<class Queue>
class Template  
{
public:
    Queue value;
    Template() = default; 
    Template(Queue input) {
        value = input;
    }
};

template<typename T>
std::ostream& operator<<(std::ostream& os, Template<T> const& t)
{
    os << t.value; 
    return os; 
}

int main ()
{
    using v_t = boost::variant<Template<int>, Template<string>>; 

    v_t ar[2]; 

    ar[0] = Template<int>(1); 
    ar[1] = Template<string>("lmfao"); 

    for (auto&& elem : ar) cout << elem << endl;
}

Demo

注意

  • v_t 是变体的类型
  • v_t 可以有更多类型,您可以选择填充数组
  • 输出运算符仅为演示而重载
  • boost::visitor 为您提供额外的功能

【讨论】:

    猜你喜欢
    • 2017-09-10
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 2021-04-24
    • 2017-01-13
    • 2020-12-19
    • 2017-05-14
    相关资源
    最近更新 更多