【问题标题】:Proper representation of ArrayList<Object> of Java in C++在 C++ 中正确表示 Java 的 ArrayList<Object>
【发布时间】:2015-04-07 22:10:02
【问题描述】:

在 Java 中,我使用

ArrayList<Object> contents = new ArrayList<Object>();

保存泛型类型,并且元素不应该属于同一类型。

例如,我做了这样的事情:

int n = 1991;
String str = "mfso";
contents.add(n);
contents.add(str);

现在,我想在 C++ 中做同样的事情,但我没有发现任何相似之处。 我尝试了 `void**,但它非常类似于 C,而且很难驾驭。我想要一个更面向对象的解决方案。

我希望你能告诉我不同​​的解决方案,并简要告诉我优缺点。

提前致谢

周可岑

【问题讨论】:

  • 说实话,在容器中存储any类型并不是特别的OO。您最终不得不创建许多 OO 应该避免的 if() 类型的分支。要成为 OO,您确实需要存储在容器中的类型是强相关的,因此每个类型 都是一些常见的基本类型接口的一种

标签: java c++ oop


【解决方案1】:

C++ 没有像 Java 的 Object 类这样的“通用基类”。因此,必须以其他方式创建此机制。

对于真正的“任何东西”容器,唯一通用的解决方案是使用Boost.Any 库中的boost::any 之类的东西(某些编译器也可能支持std::experimental::anyas described here)。使用它显然有开销,但我认为这是你准备好接受的东西。

你可以这样使用它:

#include <vector>
#include <string>
#include <iostream>
#include <typeinfo>

#include <boost/any.hpp>

int main() {
  std::vector< boost::any > contents;

  int n = 1991;
  std::string str = "mfso";
  contents.emplace_back(n);
  contents.emplace_back(str);

  for(auto& x : contents) {
    if( x.type() == typeid(int) )
      std::cout << " Int: " 
                << boost::any_cast< int >(x) << std::endl;
    else if( x.type() == typeid(std::string) )
      std::cout << " String: " 
                << boost::any_cast< std::string& >(x) << std::endl;
  };
};

理想情况下,如果您可以通过其他方式解决问题,则应避免使用 boost::any 之类的内容。例如,如果所有类型的对象都通过某个基类相关(或可以相关),那么您应该使用它。或者,如果您希望在容器中存储的类型数量有限,那么您可以改用 boost::variant 之类的东西(请参阅 docs)。

【讨论】:

  • 非常感谢。我认为从 Java 到 C++ 的相当直接的翻译是不可能的,我不应该这样假设。
【解决方案2】:

您正在寻找使用模板。模板是一种 C++ 语言结构,它允许编译器通过允许参数化类型(我的)来生成类类型或函数的多个版本。

template <class Obj>
class Foo
{
   private:
      Obj n;
      int x;
      //... more variables etc..

}

实施:

Foo<string> t;
Foo<yourObject> s;
t.yourmethod(someParam);

【讨论】:

    【解决方案3】:

    如果您不希望项目中的 boost 开销(如果您问我的话,这是相当大的),您可以执行以下操作:

    std::vector<void*> contents;
    
    int n = new int(9);
    std::string s = new string("hello");
    contents.push_back(n);
    contents.push_back(s);
    
    // get the contents
    if (typeid(*contents[0]).name() == std::string("int")) {
        std::cout << "contents[0] is an int" << std::endl;
    }
    // so on and so forth
    

    请注意,这不是 C++ 做事的方式。如果你打算尝试在 C++ 中编写 Java,你会遇到困难,所以我建议学习惯用的做事方式。

    【讨论】:

    • 该技术不可移植,因为 type_info::name 返回的字符串是实现定义的。
    猜你喜欢
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 2015-05-02
    • 2021-08-30
    • 2017-07-03
    • 2010-11-28
    • 1970-01-01
    相关资源
    最近更新 更多