c++ - 在 std::vector 中模板化存储多个不同类型

标签 c++ templates c++11 vector casting

谢谢大家的宝贵时间,我真的很感激。

需要使用模板化方式在 std::vector 中存储多个不同类型的变量。要使用以下函数,程序员必须知道他们存储变量的顺序以及存储的变量数量。

class _NetVar {};

创建一个子类来保存实际变量:

template <class VARTYPE> class NetVar : public _NetVar
{
private:
    VARTYPE Var;
    NetVar(VARTYPE Value)
    {
        Var = Value;
    }
};

创建基类辅助类的 vector

std::vector<_NetVar> DataVec;

数据像这样放入 vector 中:

template <class DATATYPE> void AddData(DATATYPE AddData)
{
    DataVec.push_back(NetVar<DATATYPE>(AddData));
}

数据在这里从 vector 中拉出,一个内部变量保存 vector 的当前位置,并在每次请求变量时递增:

template <class DATATYPE> DATATYPE GetData()
{
    NetVar<DATATYPE> Temp = PacketData[VecPos];

    return Temp.Var;
    ++VecPos;
}

前面的函数出问题了,可以将子类识别为基类,但是否可以将基类识别为它的子类之一?

下面是代码的使用方式:

AddData<int>(32);
AddData<bool>(true);
AddData<std::string>("Test");

auto Var1 = GetData<int>();
auto Var2 = GetData<bool>();
auto Var3 = GetData<std::string>();

调用 GetData 时抛出异常:

'initializing' : cannot convert from '_NetVar' to 'NetVar<DATATYPE>'

如果有人能帮我解决这个问题,我将不胜感激,再次感谢您的宝贵时间。

注意:需要避免使用 Boost 等外部库。

最佳答案

vector 应该是:

std::vector<_NetVar *> DataVec;

或高级指针

std::vector<std::shared_ptr<_NetVar> > DataVec;

这样你就可以存储子类的实例而不是 slicing他们到基类。

在 GetData 上,您需要向上转换从 vector 中检索到的指针。


编辑:添加完整的工作代码

处理 ideone 的示例, 不得不稍微调整一下权限。

并且该示例添加了一些注释。

#include <iostream>
#include <vector>
#include <memory>
class _NetVar {};

template <class VARTYPE> 
class NetVar : public _NetVar
{
private:
    VARTYPE Var;
public:
    NetVar(VARTYPE Value)
    {
        Var = Value;
    }
};

请注意,我将 NetVar<> 构造函数和 Var 属性更改为公开...需要 AddData 和 GetData 才能访问它。

不确定在您的示例中您是否在 _NetVar 上有一些虚拟方法(在这种情况下,下面的 static_pointer_cast 可能是 dynamic_pointer_cast )

与此相关,您可能想验证是否调用了 NetVar 的析构函数(不仅是 _NetVar 的析构函数)(在 ideone 上检查过,它们在我的示例中有效,因为我使用的是 std::make_shared<NetVar<XX> >(...) )

std::vector<std::shared_ptr<_NetVar> > DataVec;
int VecPos;

为下面的函数添加了这个全局变量。

template <class DATATYPE> void AddData(DATATYPE AddData)
{
    DataVec.push_back(std::make_shared<NetVar<DATATYPE> >(AddData));
}

所以在这里我们创建一个 shared_ptr使用新对象 NetVar<DATATYPE>并将其插入 vector 中。

template <class DATATYPE> DATATYPE GetData()
{
    std::shared_ptr<_NetVar> content = DataVec[VecPos];
    std::shared_ptr<NetVar<DATATYPE> > Temp = std::static_pointer_cast<NetVar<DATATYPE> >(content);
    ++VecPos;

    return Temp->Var;
}

这里 vector 的内容是std::shared_ptr<_NetVar>这就是我们得到的。该 shared_ptr 需要向上转换为正确类型的 shared_ptr

现在有一个问题,您必须知道要向上转换到的正确类型,否则就是未定义的行为。如果你有虚拟方法,你可以使用 dynamic_pointer_cast 然后执行 null 检查...但它有一些 performance penalties

int main() {

    AddData<int>(32);
    AddData<bool>(true);
    AddData<std::string>("Test");

    auto Var1 = GetData<int>();
    auto Var2 = GetData<bool>();
    auto Var3 = GetData<std::string>();

    std::cout << Var1 << std::endl;
    std::cout << Var2 << std::endl;
    std::cout << Var3 << std::endl;
    return 0;
}

最后测试并打印结果。

关于c++ - 在 std::vector 中模板化存储多个不同类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22999539/

相关文章:

c++ - 基于标签分派(dispatch)的特化,用于 C++ 代码中的平台识别和仿真

c++ - 如果它包含多个语句,是否有理由不允许 lambdas 推断返回类型?

c++ - 将父类(super class)函数作为非类型名模板参数传递

c++ - 在 GCC 4.7.2 和 Clang 3.2 中显然缺少 getline() 的重载,将 RRef 流式传输

c++ - 使用递归反向链表

c++ - 有人对 gcc 的 LTO (C++) 有经验吗?

c++ - 我可以在基类模板方法中自动推导出子类型吗?

c++ - 模版的歧义

c++ - 在模板参数推导过程中丢失限定符

c++ - 为什么统一初始化语法只适用于对象?