C++ 在C+中存储任意对象的列表+;
在Java中,可以有一个对象列表。您可以添加多种类型的对象,然后检索它们,检查它们的类型,并对该类型执行相应的操作。C++ 在C+中存储任意对象的列表+;,c++,collections,types,C++,Collections,Types,在Java中,可以有一个对象列表。您可以添加多种类型的对象,然后检索它们,检查它们的类型,并对该类型执行相应的操作。 例如:(如果代码不完全正确,我会道歉,我会用记忆) List List=newlinkedlist(); 添加(“你好,世界!”); 增加(7); list.add(true); 用于(对象o:列表) { if(o instanceof int) ;//如果是int,则执行一些操作 else if(o字符串实例) ;//如果是字符串,就做一些事情 else if(布尔值的o实例)
例如:(如果代码不完全正确,我会道歉,我会用记忆)
List List=newlinkedlist();
添加(“你好,世界!”);
增加(7);
list.add(true);
用于(对象o:列表)
{
if(o instanceof int)
;//如果是int,则执行一些操作
else if(o字符串实例)
;//如果是字符串,就做一些事情
else if(布尔值的o实例)
;//如果是布尔型的,就做一些事情
}
<> P> C++中的复制行为最好的方法是什么?< /P> < P> C++不支持异构容器。 如果您不打算使用
boost
,那么hack就是创建一个虚拟类,并让所有不同的类都从这个虚拟类派生出来。创建一个您选择的容器来保存虚拟类对象,您就可以开始了
class Dummy {
virtual void whoami() = 0;
};
class Lizard : public Dummy {
virtual void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter : public Dummy {
virtual void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::list<Dummy*> hateList;
hateList.insert(new Transporter());
hateList.insert(new Lizard());
std::for_each(hateList.begin(), hateList.end(),
std::mem_fun(&Dummy::whoami));
// yes, I'm leaking memory, but that's besides the point
}
您可以创建一个基类,然后创建从基类继承的类。然后,将它们存储在std::vector中。我是一个相当缺乏经验的人,但以下是我的建议-
我希望这有帮助遗憾的是,C++中没有简单的方法。您必须自己创建一个基类,并从该类派生所有其他类。创建一个基类指针向量,然后使用dynamic_cast(它有自己的运行时开销)查找实际类型。类似于Dirkenty的建议,即
boost::any
,但支持访问者模式,这意味着以后更容易添加特定类型的代码。此外,它在堆栈上分配值,而不是使用动态分配,从而使代码的效率略高
EDIT:正如litb在评论中指出的那样,使用variant
而不是any
意味着您只能保存一个预先指定的类型列表中的值。这通常是一种优势,尽管在询问者的案例中可能是一种劣势
下面是一个示例(但不使用访问者模式):
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
...
向量v;
对于(int i=0;i
(是的,从技术上讲,你应该使用
vector::size_type
而不是int
来表示i
的类型,从技术上讲,你应该使用vector::iterator
,但我尽量保持简单。)简单的答案是。。。你不能
长话短说的答案是。。。您必须定义自己的对象继承权,这些对象都继承自基础对象。在Java中,所有对象最终都是从“对象”派生出来的,而“对象”正是允许您这样做的原因。这类事情实际有用的频率有多高?我已经在C++中编程了好几年,在不同的项目上,从来没有真正想要一个异质容器。在java中,由于某种原因(java语言的经验),这在java中可能很常见,但是对于Java项目中的任何给定的使用,可能有一种方法来做不同的C++工作。 C++比Java更强调类型安全,这是非常不安全的 也就是说,如果这些对象没有共同点,为什么要将它们存储在一起 如果他们有共同点,你可以为他们创建一个类来继承;或者,使用boost::any。如果它们继承,有虚拟函数调用,或者如果需要,使用DyrimeSkyCase.
RTI(运行时类型信息)在C++中一直是困难的,特别是交叉编译器。 最好的选择是使用STL并定义一个接口,以确定对象类型:
public class IThing
{
virtual bool isA(const char* typeName);
}
void myFunc()
{
std::vector<IThing> things;
// ...
things.add(new FrogThing());
things.add(new LizardThing());
// ...
for (int i = 0; i < things.length(); i++)
{
IThing* pThing = things[i];
if (pThing->isA("lizard"))
{
// do this
}
// etc
}
}
公共类信息
{
虚拟布尔isA(常量字符*类型名);
}
void myFunc()
{
向量事物;
// ...
添加(新的FrogThing());
添加(新蜥蜴事物());
// ...
for(int i=0;iisA(“蜥蜴”))
{
//这样做
}
//等
}
}
迈克除此之外,正如大多数人所指出的,你不能这样做,或者更重要的是,很可能你真的不想这样做 让我们摒弃你的例子,考虑更接近现实的例子。具体来说,我在一个真正的开源项目中看到了一些代码。它试图在字符数组中模拟cpu。因此,它将在数组中放入一个单字节的“操作码”,后跟0、1或2个字节,这些字节可以是字符、整数或基于操作码的字符串指针。要处理这个问题,需要做很多的修改 我的简单解决方案是:4个独立的stackss:一个用于“操作码”枚举,一个用于char、int和string。取下操作码堆栈中的下一个,则将取其他三个中的哪一个来获取操作数
您的实际问题很有可能以类似的方式得到处理。使用Boost.Variant和访问者的示例:
#include <string>
#include <list>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
typedef variant<string, int, bool> object;
struct vis : public static_visitor<>
{
void operator() (string s) const { /* do string stuff */ }
void operator() (int i) const { /* do int stuff */ }
void operator() (bool b) const { /* do bool stuff */ }
};
int main()
{
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
BOOST_FOREACH (object& o, List) {
apply_visitor(vis(), o);
}
return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
类型定义变量对象;
结构vis:公共静态访问者
{
void运算符()(字符串s)常量{/*do string stuff*/}
void运算符()(int i)常量{/*do int stuff*/}
void运算符()(布尔b)常量{
#include <vector>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
...
vector<variant<int, string, bool> > v;
for (int i = 0; i < v.size(); ++i) {
if (int* pi = get<int>(v[i])) {
// Do stuff with *pi
} else if (string* si = get<string>(v[i])) {
// Do stuff with *si
} else if (bool* bi = get<bool>(v[i])) {
// Do stuff with *bi
}
}
public class IThing
{
virtual bool isA(const char* typeName);
}
void myFunc()
{
std::vector<IThing> things;
// ...
things.add(new FrogThing());
things.add(new LizardThing());
// ...
for (int i = 0; i < things.length(); i++)
{
IThing* pThing = things[i];
if (pThing->isA("lizard"))
{
// do this
}
// etc
}
}
#include <string>
#include <list>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
typedef variant<string, int, bool> object;
struct vis : public static_visitor<>
{
void operator() (string s) const { /* do string stuff */ }
void operator() (int i) const { /* do int stuff */ }
void operator() (bool b) const { /* do bool stuff */ }
};
int main()
{
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
BOOST_FOREACH (object& o, List) {
apply_visitor(vis(), o);
}
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a = 4;
string str = "hello";
vector<void*> list;
list.push_back( (void*) &a );
list.push_back( (void*) &str );
cout << * (int*) list[0] << "\t" << * (string*) list[1] << endl;
return 0;
}
class MyData
{
public:
// base classes of polymorphic types should have a virtual destructor
virtual ~MyData() {}
// hand off to protected implementation in derived classes
void DoSomething() { this->OnDoSomething(); }
protected:
// abstract, force implementation in derived classes
virtual void OnDoSomething() = 0;
};
class MyIntData : public MyData
{
protected:
// do something to int data
virtual void OnDoSomething() { ... }
private:
int data;
};
class MyComplexData : public MyData
{
protected:
// do something to Complex data
virtual void OnDoSomething() { ... }
private:
Complex data;
};
void main()
{
// alloc data objects
MyData* myData[ 2 ] =
{
new MyIntData()
, new MyComplexData()
};
// process data objects
for ( int i = 0; i < 2; ++i ) // for each data object
{
myData[ i ]->DoSomething(); // no type cast needed
}
// delete data objects
delete myData[0];
delete myData[1];
};