模板对象数组

Array of template objects

本文关键字:数组 对象      更新时间:2023-10-16

我不知道如何解决模板和继承的问题。

在我的代码中有一个模板化类,它看起来或多或少像:

template<typename T>
class Derived : public Base{
     T value;
public:
     Derived(T arg) { value=arg; };
     T getValue() { return value;};
};
class Base{
};

基类的唯一目的是对派生类的对象数组进行分组。形参T通常是双精度、浮点数或复数,尽管int和struct也可能有用。(以后应该会有几个类似的派生类,带有一些额外的函数。)

我可以创建这样一个组

Base** M = new Base*[numElements];

,并将派生类的元素赋值给它们,例如:

M[54] = new Derived<double>(100.);

但是我怎样才能知道第55个元素的值是100呢?我需要像

这样的东西
virtual T getValue() = 0;

Visitor模式可能是您最好的选择。迭代数组的代码必须提供一个"访问者"对象,该对象知道如何处理每种不同的类型。

struct NumericVisitor
{
    virtual void visit(double) = 0;
    virtual void visit(int) = 0;
    virtual void visit(unsigned char) = 0;
};
struct Visitable
{
    virtual void visitValue(NumericVisitor& visitor) = 0;
};
template<typename T>
class Derived : public Visitable
{
     T value;
public:
     Derived(const T& arg) value(arg) {}
     void visitValue(NumericVisitor& visitor) { visitor.visit(value); }
};

现在你可以为你想在集合上做的每个操作定义访问者,例如,将每个元素转换为字符串,每种类型都有不同的格式,或者将每个元素存储到一个文件中,其中每种类型可以占用不同数量的空间。

您可以将重载的has_value()方法添加到Base类中:

class Base
{
public:
    virtual ~Base () {}
    virtual bool has_value (int i) {return false;}
    virtual bool has_value (double d) {return false;}
    virtual bool has_value (const std::string& s) {return false;}
    // etc.
};

您在Derived类中重写的其中一个:

template<typename T>
class Derived : public Base
{
     T value;
public:
     Derived(T arg) {value=arg;}
     T getValue() { return value;}
     virtual bool has_value (T t)
     {
         return t == value;
     }
};

例如:

bool test ()
{
    std::vector<Base*> bases;
    bases.push_back (new Derived<double> (1.234));
    bases.push_back (new Derived<int> (100));
    bases.push_back (new Derived<std::string> ("zap"));
    for(std::vector<Base*>::const_iterator iter = bases.begin (); iter != bases.end (); ++iter)
        if ((*iter)->has_value (100))
            return true;
    return false;
}

注意,你不能用一个模板化的方法替换基类中的has_value方法,因为虚方法不能被模板化。

在基类中添加一个方法"getDouble"。派生类必须实现此方法,并根据需要将自己的类型强制转换为double类型。

NO。由于两个原因,实际上不可能有这样的功能:

  1. Base不能作为模板,如你需要一个通用句柄来存储数组,可以包含任何类型的Derived like <int>, <double>, <float>, any struct <abc> .
  2. 你不能在Base里面有template virtual方法,因为语言不允许

解决这个问题的简单方法是为每个类型都有"getter"方法,如get_double(), get_int(), get_float(), get_abc()等。但是,您的Base将会被这些方法弄得乱七八糟。

您可以使用dynamic_cast来知道它是什么类型(除了@StackedCrooked所说的内容之外)。这将需要在基类中定义一些虚函数,但在那里已经需要一个虚析构函数(以便能够通过基类指针删除值)。

作为一种替代方法,您可以尝试boost::variant或boost::any:)

使用boost::any将对象存储在数组中。然后,当您想对其进行操作时,您可以使用boost::any_cast对您可能拥有的类型进行操作。