我想创建一个模板项的向量
我的方法是:
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
答案 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
调用正确的重载。
请注意,您应该使用std::unique_ptr
而不是向量的原始指针。