【问题标题】:How to simulate a void data type?如何模拟 void 数据类型?
【发布时间】:2013-11-19 01:21:42
【问题描述】:

我知道 void 指针,它们可以指向任何类型的对象。因此,如果我想要一个包含存储未知类型数据的元素的链表,我可以使用void*:

struct Node {
    Node* next;
    void* data;
};

但是如果我不想使用指针但我仍然不知道Node 将携带什么类型的数据怎么办?有没有办法让data 没有特定类型?我尝试了auto,但它不起作用,因为它需要立即推导出一个初始化程序。

【问题讨论】:

  • 您是否已经考虑过基于模板的解决方案??
  • 您想要void 的哪些方面?只是指向您选择的类型(可能在运行时确定)的能力还是阻止其他人取消引用该类型的能力?模板是获得第一个的一种方式。
  • 你想要链表的每个元素的数据类型相同还是不同?在第一种情况下使用模板,在第二种情况下使用联合(在这种情况下,您必须单独存储有关数据类型的信息)

标签: c++ void-pointers


【解决方案1】:

您想使用模板。它们是 C++ 中泛型类型的一种形式。我不会在这里写完整的教程,但这里是一般形式:

template<typename T>
return_type function_name(parameters) {

}

在创建模板化对象的情况下,您可以执行以下操作:

template<typename T>
struct struct_name {
    T member_name;
};

这里,“template”和“typename”是 C++ 中的实际关键字。 “T”可以是任何你想要的名字。

http://www.cplusplus.com/doc/tutorial/templates/

编辑:我想强调以下几点,这可能是我提供的链接中讨论的关于 C++ 模板最重要的重要事项:

因为模板是在需要时编译的,所以这会强制 多文件项目的限制:实现(定义) 模板类或函数的名称必须与其在同一个文件中 声明。 这意味着我们不能在一个 单独的头文件,我们必须同时包含接口和 在使用模板的任何文件中实现。

【讨论】:

  • cplusplus.com 充满了错误……您还有其他来源吗?另外值得注意的是,同一模板的不同参数化是不同的类型。所以这提供了一种生成不同Node 类的方法,在给定的节点中没有任何数据。
  • 老实说,我发布了我发现的第一个相关链接。如果你碰巧有一个好的链接,我会编辑我的答案。
  • 抱歉,我对教育文献不是很熟悉。这是我朋友写的一篇,准确且最新,虽然没有那么广泛,但平易近人:codepuppy.co.uk/cpptuts/Beginning/templates.php
【解决方案2】:

正如其他人所指出的,C++ 从根本上无法拥有在编译时未确定类型的对象。您似乎正在描述的一般概念称为类型擦除,一个用于透明地生成您可能实际发生的任何查询所需的所有编译时类型的过程。一个通用库是Boost.Any。现在我看到 Boost 还有一个更新的type erasure 库,用于更广泛和更高级的使用。

类型擦除仍然需要您了解对象可能拥有的类型。你会得到类似“如果可能的话,给我一个int”这样的操作。

模板不是一回事。模板Node&lt;T&gt; 将为每个 T 提供不同类型的节点,因此由节点形成的整个数据结构将专用于存储特定类型,而不是混合。这就是C++ standard library 的工作原理,您通常应该使用它而不是编写自己的数据结构。

【讨论】:

    【解决方案3】:

    使用void* 表示“任何(指针)类型的未知值”在 C 中很常见。但是在 C++ 中,有一个更好的解决方案——即使用模板。

    一般形式是:

    template <typename T>
    struct Node {
        Node* next;
        T data;
    };
    

    然后你会声明一个Node&lt;int&gt;(或者你想在你的列表中保留的任何类型)。

    模板非常强大,但也可能变得相当复杂。我建议您阅读您最喜欢的 C++ 教科书中关于它们的使用。

    【讨论】:

      【解决方案4】:

      由于c++是静态类型的,所以所有类型都必须在编译时解析。并且 void 变量不能被清除,因为编译器不知道要分配多少内存。

      可能存在运行时类型发现的错觉,但实际上这在 c++ 中是不可能的。基于模板的解决方案可能适用于某些人。但真的,我不能在变量中保存任意类型。

      【讨论】:

      • 他正在做一个指向 void 的指针,而不是一个 void 变量。那是不同的。
      • 是的。我是这么说的。可能存在运行时类型发现的错觉,但实际上这是不可能的。 @PawełStawarz
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 2019-01-11
      相关资源
      最近更新 更多