我目前希望有一个对象向量,其中每个对象具有不同的属性。
预期结果:
//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
基于this answer我尝试在模板中使用<void*>
的类构造函数,但这似乎只是创建一个指向void
的指针(正如我部分预期的那样)。 / p>
ttSaveObj.hpp:
template <typename T>
class ttSaveObj {
public:
ttSaveObj(T pVar, std::string pName) {
data = pVar;
variableName = pName;
};
~ttSaveObj() {};
std::string variableName;
T data;
};
ttGameObj.hpp:
#include "ttSaveObj.hpp"
class ttGameObj {
public:
ttGameObj();
~ttGameObj();
std::vector<ttSaveObj<void*>> data;
};
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
}
任何有助于我更接近我的预期结果的事情都表示赞赏,谢谢!
答案 0 :(得分:5)
您在向量中放置的对象似乎有两个数据成员:variableName
,其类型为固定std::string
,而data
字段为不同类型。
您可以考虑对variant
字段使用C++17's std::variant
(或Boost&#39; data
实施)。例如,如果您计划为int
支持float
,std::string
和data
类型,则可以使用std::variant<int, float, std::string>
。
还有std::any
,如果您想存储任何类型的实例(满足std::any
documentation中描述的要求)。
在现代 C ++中,我建议避免使用C风格的void*
,并且只在必要时使用它(例如,如果你处于某个传统的C API边界) :有更安全,更强大和更高级别的替代品。
另一个选项(如果它对您的设计更有意义)是为要放入向量中的对象定义基类(接口),并定义实现此接口的自定义类。在这种情况下,我建议使用 smart 指针(例如std::unique_ptr
或std::shared_ptr
)以简单安全的方式管理这些对象(我在这里看到另一个使用raw的答案)指针,需要明确的new
/ delete
- 实际上在该代码中有new
但没有delete
,导致资源泄漏。)
E.g:
#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';
}
}
输出:
10 20 Hello World
答案 1 :(得分:0)
如果您使用的是C ++ 11,则可以使用标准库中的元组类。你可以像这样制作这个对象:
auto v = std::make_tuple(ttSaveObj(5, "int example"), ttSaveObj("Hello, world!", "string example"))
std::cout << std::get<0>(v).data << " " << std::get<0>(v).variableName << std::endl;
虽然访问索引是模板参数,但是有一个缺点,因此必须在编译时知道,这意味着您无法遍历元素。此外,必须在编译时知道元组中元素的类型。
答案 2 :(得分:0)
如果我正确地理解了你的目标,就可以采用类似Java的方法,但是你应该将矢量包装成永不忘记清理。
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <string.h>
#include <memory>
using std::vector;
class Object
{
public:
explicit Object() {}
virtual ~Object() {}
virtual const char* toString() const = 0;
};
class StringObject : public Object
{
public:
explicit StringObject(const char* string) : Object()
{
if(string != 0)
{
m_value = new char[strlen(string) + 1];
strcpy(((char*)m_value), string);
} else
{
m_value = new char[1];
m_value[0] = 0;
}
}
virtual ~StringObject()
{
delete m_value;
}
virtual const char* toString() const
{
return (const char*)m_value;
}
private:
char* m_value;
};
class IntObject : public Object
{
public:
explicit IntObject(int val) : Object()
{
m_value = val;
}
virtual ~IntObject()
{
}
virtual const char* toString() const
{
return std::to_string(m_value).c_str();
}
private:
int m_value;
};
int main()
{
auto vec = vector<std::unique_ptr<Object>>();
vec.push_back(std::make_unique<IntObject>(9));
vec.push_back(std::make_unique<IntObject>(11));
vec.push_back(std::make_unique<StringObject>("hello"));
vec.push_back(std::make_unique<StringObject>("world"));
for(const auto& v : vec)
{
std::cout << v.get()->toString() << " ";
}
}
按预期输出&#34; 9 11你好世界&#34;。