C++ 在C+中存储任意对象的列表+;

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实例)

在Java中,可以有一个对象列表。您可以添加多种类型的对象,然后检索它们,检查它们的类型,并对该类型执行相应的操作。
例如:(如果代码不完全正确,我会道歉,我会用记忆)

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++编程习惯,所以我试图在不加入代码的情况下传达我的想法。
    我希望这有帮助类似于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];
    };