从std::继承类
Inheriting classes from std::
有很多类似的问题,我发现使用这种模式既有支持的理由,也有反对的理由,所以我在这里问这个:
我需要在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++专家,但是有什么特别的理由不这样做吗?
有什么特别的理由不这样做吗?
是的。你得到的是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
};
...
};
似乎你认为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类的成员。-
我不建议继承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.
};
...
};
我认为它实际上是更好的包装它在你自己的类(即代理使用std作为成员),因为它使它更加松散耦合,如果你想使用不同的数据结构,这将是相当容易的,因为你可以简单地修改你自己的类,而std类不应该被修改。如果对象的接口很简单,也许您甚至应该实现自己的接口(当您想要使用与std或boost不同的数据结构或任何适合您需求的数据结构时,使其易于兼容)。您当前的实现可能不是评论中提到的最好的,但我仍然建议在您自己的类中包装std使用(特别是在较大的应用程序中)。
- 可以从std::string继承以提供类型一致性吗
- "std::shared_from_this"不能由其派生类继承吗?
- 从 std::数组私下继承时无法从 std::initializer_list 构造
- C++ std::vector 中的虚拟析构函数继承
- 当键是虚拟继承中涉及的基类指针时,对 std::unordered_map 项的访问崩溃
- 在继承自 std::variant 的类上使用 std::visit——libstdc++ 与 libc++
- std::exception :使用虚函数和继承与变量
- 如何创建一个继承自 std::vector 的类
- 是否可以通过使用 std::variant 来避免继承
- std::bad_weak_ptr 从基类继承 std::shared_from_this 时
- C++通过继承 std::exception 来创建新的异常
- 为自定义类继承std::vector::迭代器
- 错误:当我继承 std::vector 时,在“开始”之前预期“)”
- 如何在 C++11 的用户自定义类模板中继承 std::vector 模板
- 在继承std::vector的类中使用操作符[]
- c++ -从其他对象继承std::元组,并为其添加虚函数
- 尝试继承std::runtime_error时出现编译错误
- 继承 std::容器,包括其提升序列化
- 继承std::basic_streambuf的问题
- 继承std::string类时跳过添加构造函数