【问题标题】:Is there a base class from which all members of the C++ standard library derive?是否有一个 C++ 标准库的所有成员都派生自其的基类?
【发布时间】:2016-01-18 08:30:39
【问题描述】:

C++/CLI 有一个 System::Object 类来实现这个目的,但我似乎在标准库中找不到。基本上我正在编写一组类,我希望基类将std::string 的向量存储在content 属性中,但派生类可能需要存储其他东西的向量(甚至可能是我的一个自己的班级)。这似乎是一个奇怪的目标,但我正在编写一些文件访问类来让我更轻松地操作不同格式的文件。基类 File 将每一行存储在一个字符串中,作为向量的一部分 - 但例如 JSON 的一个类可能需要存储 JS 样式的集合/对象等。

我能想到的唯一方法是让 content 属性成为对象向量(或其他一些通用基类 - 为了多态性,我也可以从中派生任何自定义类),然后将其转换回根据正在使用的子对象的类型,进入任何必要的类型。我很快发现我在任何地方都找不到任何提及std::object(或类似名称)的内容。

这个例子应该展示我想要做什么:

class File {
protected:
    std::vector<std::object> _content;

public:
    //Contructors/methods/etc.

    std::string getItemAt(size_t index) {
        return static_cast<std::string>(this->_content[index]);
    }

    void setItemAt(size_t index, std::string value) {
        this->_content[index] = static_cast<std::object>(value);
    }
};

class JSONFile: File {
public:
    //Constructors/methods/etc.

    SomeObject getItemAt(size_t index) {
        return static_cast<SomeObject>(this->_content[index]);
    }

    void setItemAt(size_t index, SomeObject value) {
        this->_content[index] = static_cast<std::object>(value);
    }
};

请注意,此示例假定 std::object 存在,并且 SomeObject 将是用于处理 JSON(再次,例如 - 这可能是任何东西)数据的任何内容。 SomeObject 显然会派生自 std::object

任何建议都将不胜感激,如果我在这方面完全走错了路,任何关于我如何做到这一点的反馈,这样std::object 的事情就没有必要了将不胜感激:)

【问题讨论】:

  • 我不明白你为什么要寻找像std::object 这样的东西。如果你自己的类需要一个基类,就写一个
  • 查看boost::any
  • @tobi303 实际上我需要在 std::string as well 之间转换为我自己的类 - 因此我的困境
  • @BradSullivan 对不起,我仍然没有看到问题。只需编写包含std::stringstd::whateverXYZ::My_own_class 的类(从您的基类继承)

标签: c++ oop c++11 polymorphism base-class


【解决方案1】:

是否有一个 C++ 标准库的所有成员都派生自其的基类?

简短的回答是“不”。
长答案是“绝对不是”。

可以在相关的 SO 网站上查看提供更多详细信息的答案:Why is base-for-all-objects discouraged in C++

【讨论】:

  • 您能否详细说明“非常长的答案”?浏览答案以查看“为什么不”而不是绝对答案对我来说更有用。
【解决方案2】:

没有。

因为 C++ 的宗旨就是“只为使用的东西付费”。

std::object 的界面会是什么样子?如果有任何成员函数,则必须是 virtual 才能使用,由于动态调度导致运行时成本。

如果假设的std::object 是一个空类,你可以用std::object 引用做什么?不多,因为它没有任何成员函数可以调用。既然没有共同点,为什么还要让所有东西都来自一个基础。


如果您真的需要所有类的基础,您可以随时编写一个。但请注意,这样做might nota good design decision

【讨论】:

  • 这是一个公平的观点。你知道为什么 C++/CLI 实现了一个吗?
  • 我喜欢这个思考过程。我想扩展您还想考虑假设的 std::object 的存储要求是将其存储在连续数组中。
  • @BradSullivan:实施Common Type System :) 您可以在What's So Common About the Common Type System 找到更多信息
  • @Landon 作为一个抽象类(假设),您只能将指向它的指针存储在数组中。
  • @Landon 啊,好吧,所以标准 C++ 中不需要通用类型系统,因为它不需要与其他语言兼容。有道理:)
【解决方案3】:

当我看到你定义时

std::vector<std::object> _content;

它告诉我,您的目标是使用模板进行通用编程,而不是使用继承进行面向对象编程。这是 std::vector 和 co. 的同一种风格,所以看起来应该不会太陌生。

您的代码可能是:

template <typename FileObject>
class File {
public:
    std::vector<FileObject> _content;

public:
    //Constructors/methods/etc.

    FileObject getItemAt(size_t index) {
        return this->_content[index];
    }

    void setItemAt(size_t index, std::string value) {
        this->_content[index] = FileObject(value);
    }
};

然后将其用作

json_files = File<JSONObject>();
json_files.setItemAt(1, "{}");

或者,如果您想对 json 对象列表执行特殊操作,该函数可以采用显式 File&lt;JSONObject&gt; 参数。也可以从 File&lt;JSONObject&gt; 继承,但不鼓励混合和匹配 OO/Generic。

现在,更接近您的标题问题:您不能轻松地将不同的文件类型存储在同一个向量中,但请考虑如何实现它。 File&lt;int&gt; 的存储要求是什么?对于File&lt;double&gt;?这是一个核心点,您的 OO/继承解决方案将变得笨拙,并且使用泛型编程无法尝试,这很好。

【讨论】:

  • 哎呀,这条评论实际上并没有回答你关于核心基类的问题,而是切入你的界面的核心问题。
  • 这真的很棒 - 谢谢!我也确实征求过建议,所以这个答案绝对是有效的。
  • 谢谢。我想知道为什么发布后它被大量反对票淹没。
  • 这与通用基类的功能不太一样;模板参数必须在编译时知道。
  • 在他的用例中,由于想要一个 JSONFile,他已经在编译时知道了类型。不过一般来说,你是对的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-27
  • 2011-09-17
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
相关资源
最近更新 更多