矢量模板 - >使用儿童班的成员

时间:2016-01-26 08:35:14

标签: c++ templates vector

我想创建一个模板项的向量

我的方法是:

class InterfaceItem
{
}

template <typename T>
class Item : public InterfaceItem
{
 T value;
 T GetValue();
}

std::vector<InterfaceItem*> items;
items.push_back(new Item<int>());

这种方法到目前为止工作,但现在我有问题来访问我的项目值。最好的方法是什么?

我考虑过保存基类中的子类型,然后将一个类型转换为此子类,但是我只能使用默认类型或已知类型。

你获得什么方法

auto value = items[0].GetValue(); // will not compile

3 个答案:

答案 0 :(得分:0)

  

访问我的项目值时出现问题。最好的方法是什么?

与继承一起使用的典型设计是通过接口访问值。要通过接口访问某些内容,它必须具有成员函数。并且为了从接口获得多态行为,成员函数应该是虚拟的。并且,由于接口本身不能实现成员函数,并且任何派生类可能都应该,它应该是纯虚拟成员函数。此外,如果您打算使用基指针存储派生对象,请不要忘记使用虚拟析构函数。这是一个例子:

class InterfaceItem {
    virtual int GetValue() = 0;
    virtual ~InterfaceItem();
};

class Item: public InterfaceItem {
    int GetValue() override;
}

现在,这将有效:

auto value = items[0]->GetValue();

请注意,接口函数不是模板化的。编译时多态(模板)和运行时多态(继承)并不总是很好。您无法覆盖模板功能。通常,您必须选择要使用的多态性类型。

答案 1 :(得分:0)

在这种情况下,您不需要继承。只需:

#include <vector>

template <typename T>
struct Item {
    T value;
    T GetValue(){return value;}
};

int main() {
    std::vector<Item<int>*> items;
    items.push_back(new Item<int>());
    auto value = items[0]->GetValue(); // will compile
}

请勿忘记删除这些项目,或使用std::unique_ptr<>

的向量

答案 2 :(得分:0)

你可以做某种访客模式。

首先,建立一个可以访问您将要使用的所有类型的基本访问者类:

class ItemVisitor {
public:
     virtual void visit (int a) = 0;
     virtual void visit (std::string a) = 0;
     virtual void visit (double a) = 0;
};

然后让InterfaceItem接受ItemVisitor

class InterfaceItem
{
public:
    virtual void accept(ItemVisitor& visitor) = 0;
};

现在,不要使用GetValue,而是在visit内的访问者上致电Item

template <typename T>
class Item : public InterfaceItem
{
public:
    Item (T t) : value{std::move(t)} {}
    void accept(ItemVisitor& visitor) override { visitor.visit(value); }

private:
    T value;
};

现在,当您想要访问您的项目时,请写一个访问者来完成所有工作:

class PrintVisitor : public ItemVisitor {
    void visit (int a) override { std::cout << "int " << a << '\n'; }
    void visit (std::string a) override { std::cout << "std::string " << a << '\n'; }
    void visit (double a) override { std::cout << "double " << a << '\n'; } 
};

然后创建访问者的实例并使用它来访问具有已删除类型的元素:

int main() {
    std::vector<InterfaceItem*> items;
    items.push_back(new Item<int>(42));
    items.push_back(new Item<std::string>("Hi there"));
    items.push_back(new Item<double>(42.12));
    items.push_back(new Item<int>(24));

    PrintVisitor visitor{};

    for (auto i : items) {
        i->accept(visitor);
    }
}

这将为每个项目visit内的PrintVisitor调用正确的重载。

Live Demo

请注意,您应该使用std::unique_ptr而不是向量的原始指针。