模板对象的数组

时间:2011-04-30 15:31:45

标签: c++ templates polymorphism

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

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

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

class Base{
};

我的Base类的唯一目的是对Derived类的对象数组进行分组。参数T通常是double,float或complex,尽管int和structs也可能变得有用。 (稍后应该有几个类似的派生类和一些附加功能。)

我可以创建这样一个组

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

并将派生类的元素分配给它们,例如:

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

但是我怎么能发现第55个元素后来有价值100? 我需要像

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

但是T是派生类的类型名称,对于此数组的任何两个元素可能不同。

6 个答案:

答案 0 :(得分:4)

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); }
};

现在,您可以为要对集合执行的每项操作定义访问者,例如将每个元素转换为字符串,每种类型具有不同的格式,或将每个元素存储到文件中,其中每种类型可占用不同的空间量。

答案 1 :(得分:2)

您可以将重载的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;
     }
};

E.g:

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;
}

注意,您不能使用单个模板化方法替换Base类中的has_value方法,因为无法模拟虚拟方法。

答案 2 :(得分:0)

将方法“getDouble”添加到基类。然后派生类必须实现此方法,并在需要时将它们自己的类型转换为double。

答案 3 :(得分:0)

您可以使用dynamic_cast来了解它的类型(除了@StackedCrooked所说的内容)。 它需要在基类中定义一些虚函数,但是你已经需要一个虚拟析构函数(能够通过基类指针删除值)。

作为替代方案,您可以尝试使用boost :: variant或boost :: any:)

答案 4 :(得分:0)

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

  1. Base不能像你一样成为模板 想要一个通用句柄来存储 数组,可以包含任何类型的 Derived,如<int>, <double>, <float>, any struct <abc>
  2. template virtual内无法使用Base方法, 因为语言不允许它
  3. 解决此问题的简单方法是为get_double()get_int()get_float()get_abc()等所有类型设置“getter”方法。但是,您的Base将会混淆这些方法。

答案 5 :(得分:0)

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