如何在具有不同参数类型的对象中同时使用向量?

Tra*_*les 1 c++ templates pointers vector

我目前希望有一个对象向量,其中每个对象具有不同的属性.

预期结果:

//v is a vector
v.push_back(ttSaveObj(5, "int example"));
v.push_back(ttSaveObj("Hello, world!", "string example"));

std::cout << v[0].data << " " << v[0].variableName << std::endl; //Intended Output: 5 int example
std::cout << v[1].data << " " << v[1].variableName << std::endl; //Intended Output: Hello, world! string example
Run Code Online (Sandbox Code Playgroud)

根据这个答案,我尝试<void*>在模板中为类创建一个构造函数,但这似乎只是创建一个指针void(正如我部分预期的那样).

ttSaveObj.hpp:

template <typename T>
class ttSaveObj {
  public:

    ttSaveObj(T pVar, std::string pName) {
      data = pVar;
      variableName = pName;
    };
    ~ttSaveObj() {};

    std::string variableName;
    T data;
};
Run Code Online (Sandbox Code Playgroud)

ttGameObj.hpp:

#include "ttSaveObj.hpp"

class ttGameObj {
  public:

    ttGameObj();
    ~ttGameObj();
    std::vector<ttSaveObj<void*>> data;
};
Run Code Online (Sandbox Code Playgroud)

ttGameObj.cpp:

#include "ttGameObj.hpp"

ttGameObj::ttGameObj() {
  int asdf = 5;
  int * test = &asdf;
  data.push_back(ttSaveObj<void*>(test, "X"));
  std::cout << &data[0].data << " " << data[0].variableName << std::endl; //Output: 0x15fb770 X
}
Run Code Online (Sandbox Code Playgroud)

感谢所有能帮助我更接近我的预期结果的东西!

Mr.*_*C64 5

放在向量中的对象似乎有两个数据成员:variableName具有固定std::string类型的数据,以及具有不同类型的data字段.

您可以考虑在该字段中使用C++ 17std::variant(或Boost的variant实现)data.例如,如果您计划支持的类型int,floatstd::string为您的data,您可以使用 std::variant<int, float, std::string>.

还有std::any,如果你想存储的情况下,任何类型(即满足中所述的要求std::any的文档).

现代 C++中,我建议避免使用C风格void*,并且仅在严格必要时使用它(例如,如果您处于某些传统的C API边界):有更安全,更强大和更高级别的替代方案.


另一个选项(如果它对您的设计更有意义)是为要放入向量中的对象定义基类(接口),并定义实现此接口的自定义类.在这种情况下,我建议使用智能指针(如eg std::unique_ptrstd::shared_ptr)以简单和安全的方式管理这些对象(我在这里看到另一个使用原始指针的答案,需要显式new/ delete- 实际上在代码中有news但是没有delete,随之而来的资源泄漏).

例如:

#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;

// Interface for an element to be inserted in the vector
class IElement
{
public:
    IElement() {}
    virtual ~IElement() {}

    virtual string ToString() = 0;

    // Other virtual methods ...
};

class IntElement : public IElement
{
public:
    explicit IntElement(int n) : _n{ n } {}

    virtual string ToString() override
    {
        return to_string(_n);
    }

private:
    int _n;
};

class StringElement : public IElement
{
public:
    explicit StringElement(const string& s) : _s{ s } {}

    virtual string ToString() override
    {
        return _s;
    }

private:
    string _s;
};

int main() 
{
    vector<shared_ptr<IElement>> elements;
    elements.push_back(make_shared<IntElement>(10));
    elements.push_back(make_shared<IntElement>(20));
    elements.push_back(make_shared<StringElement>("Hello"));
    elements.push_back(make_shared<StringElement>("World"));

    for (const auto& e : elements)
    {
        cout << e->ToString() << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

10
20
Hello
World
Run Code Online (Sandbox Code Playgroud)