模板对象数组

发布于 2024-11-04 03:29:42 字数 663 浏览 0 评论 0原文

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

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

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

class Base{
};

我的基类的唯一目的是对派生类的对象数组进行分组。参数 T 通常是双精度型、浮点型或复数型,尽管 int 和结构也可能有用。 (稍后应该有几个更类似的派生类,并具有一些附加功能。)

我可以创建这样一个组

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

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

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

但是我怎样才能发现第 55 个元素稍后的值为 100 ? 我需要类似的东西

virtual T getValue() = 0;

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

I don't know how to resolve a problem with templates and inheritance.

In my code there is a templated class which looks more or less like:

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

class Base{
};

The only purpose of my Base class is to group an array of objects of the Derived class. The parameter T is generally double, float or complex, although int and structs might also become useful. (There should be several more similar derived classes with a few additional functions, later.)

I can create such a group

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

and assign elements of the derived class to them, e.g.:

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

But how can I find out that the 55th element has value 100 later?
I would need something like

virtual T getValue() = 0;

but T is a typename of the derived class and may be different for any two elements of this array.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜吻♂芭芘 2024-11-11 03:29:42

Visitor 模式可能是您最好的选择。迭代数组的代码必须提供一个“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); }
};

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

The Visitor pattern is probably your best bet here. The code iterating the array has to provide a "Visitor" object that knows how to handle each of the various types.

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

Now you can define visitors for each operation you want to do on the collection, e.g. convert each element to a string, with a different format for each type, or store each element into a file, where each type can take up a different amount of space.

傲影 2024-11-11 03:29:42

您可以将重载的 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 方法,因为虚拟方法无法模板化。

You could add overloaded has_value() methods to the Base class:

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

one of which you which you override in the Derived class:

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

Note, you can't replace the has_value methods in the Base class with a single templated method as virtual methods can't be templated.

待天淡蓝洁白时 2024-11-11 03:29:42

将方法“getDouble”添加到您的基类中。然后,派生类必须实现此方法,并根据需要将其自己的类型强制转换为 double。

Add a method "getDouble" to your base class. The derived classes must then implement this method and cast their own type to double if required.

舟遥客 2024-11-11 03:29:42

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

  1. Base 不能是模板,因为你
    想要一个通用句柄来存储
    数组可以包含任何类型
    派生,如
    任何结构
  2. 您不能拥有模板
    Base 内的 virtual
    方法,
    因为语言不允许

解决这个问题的简单方法是为每种类型提供“getter”方法,例如 get_double()get_int()get_float()、get_abc() 等等。但是,您的 Base 将会因此类方法而变得混乱。

NO. It's not possible practically to have such function, because of 2 reasons:

  1. Base can't be template, as you
    want a generic handle to store an
    array which can contain any type of
    Derived like <int>, <double>, <float>,
    any struct <abc>
    .
  2. You can not have a template
    virtual
    method inside Base,
    because language doesn't allow it

Plain simple way to solve this problem is to have "getter" method for every type like get_double(), get_int(), get_float(), get_abc() and so on. However, your Base will be cluttered with such methods.

感受沵的脚步 2024-11-11 03:29:42

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

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

You can use dynamic_cast to know what a type is it (in addition to what @StackedCrooked says).
It would require some virtual functions defined in the base class, but you already need a virtual destructor there (to have the ability to delete values through base class pointers).

As an alternative, you might try boost::variant or boost::any :)

吐个泡泡 2024-11-11 03:29:42

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

use boost::any to store the objects in the array. Then when you want to operate on it, you can use boost::any_cast to the possible types you have.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文