从std ::继承类

时间:2014-06-01 20:02:56

标签: c++ json c++11

有许多类似的问题,我发现使用这种模式的原因和反对理由,所以我在这里问这个问题:

我需要在C ++中创建一个JSON实现(假设它有点像家庭作业)。我想这样做:

namespace JSON {
  class JSON { };
  class object : public JSON, public std::unordered_map<std::string,JSON> { };
  class vector : public JSON, public std::vector<JSON> { };
  class string : public JSON, public std::string { };
  ...
};

如果你考虑一下,这一切都有意义。 JSON对象“is-an”unordered_map,JSON向量“is-a”向量,依此类推。只是它们也是JSON值,例如,JSON向量可以包含任何类型的JSON值(对象,向量,字符串等)。你也可以获得很多好处,然后你可以在C ++中“自然地”使用JSON(你可以在json [“mystringlist”]中有一个实际的std :: string向量,json实际上是一个unordered_map)。

我不是真正的C ++专家,但有什么特别的理由不这样做吗?

4 个答案:

答案 0 :(得分:2)

  

有什么特别的理由不这样做吗?

是。你用这个获得的是UB。问题来自std::容器不支持多态性。它们不是为了继承而设计的(没有虚拟析构函数),这意味着你不能编写正确/安全的析构函数序列。

相反,您的解决方案可能应该如下所示:

namespace XYZ { // <-- cannot have same name as class here
    class JSON { };
    class object : public JSON {
        std::unordered_map<std::string,JSON> values;
    public:
        JSON& operator[]( const std::string& key );
    };
    class vector : public JSON {
        // same here
    };
  ...
}; 

答案 1 :(得分:1)

  • 我不建议继承自STL。

  • 由于性能原因 STL标准容器没有虚拟析构函数,因此您无法以多态方式处理它们。

  • 这意味着无法使用运行时多态,并期望为它们提供正确的解析器。

  • 继承STL虽然是完全允许的,但大部分时间都表示糟糕的设计。我建议不要遵循继承自方式,而是方式:


namespace JSON {
  class JSON { };
  class object : public JSON 
  { 
    std::unordered_map<std::string, JSON> m;

    public:
    // provide interface to access m.
    };
  class Vector : public JSON { 
    std::vector<JSON> v;

    public:
    // provide interface to access v.
  };
  ...
};

答案 2 :(得分:1)

您似乎认为JSON对象是无序映射,因此它应该从std::unordered_map继承。我认为你在这里做出了合乎逻辑的跳跃。一个JSON对象绝对是你所描述的“无序地图”的例子,但它真的是std::unordered_map吗?我不会这么说。要说它是std::unordered_map表明它应该共享std::unordered_map的接口,并且应该能够在使用std::unordered_map的任何地方使用。我建议std::unordered_map的接口比JSON对象更复杂,更低级别。

除此之外,大多数情况下标准库类不是用作基类(特别是如果它们以多态方式使用的话)。

考虑到这两点,我建议你用标准库组件的术语表示你的JSON类更有意义,但不能用 is-a表示关系。而是使用标准库组件作为JSON类的成员。

答案 3 :(得分:0)

我认为最好将它包装在你自己的类中(即使用std作为成员的代理),因为它使它更加松散耦合,如果你想使用不同的数据结构,那将非常容易,因为您可以简单地修改自己的类,而不应该修改std类。如果对象的界面很简单,也许你甚至应该实现自己的界面(当你想要使用std或boost中的不同数据结构或任何适合你需要的数据时,使其易于兼容)。您当前的实现可能不是评论中提到的最佳实现,但我仍然建议在您自己的类中包装std用法(特别是在较大的应用程序中)。