【问题标题】:The "object" data type in C++?C++ 中的“对象”数据类型?
【发布时间】:2018-10-10 21:29:01
【问题描述】:

我发现了一些与我有关的问题,但它们并没有真正回答我的问题。在 Java 和 C# 中,我们有一个“object”数据类型(或在 C# 中是“var”),它可以像任何东西一样存储。例如,我想使用一个二维数组,它的类型设置为对象,所以我也可以在其中存储整数和字符串。但我真的很想念 C++ 中的这一点。据我所知,在 C++ 中有模板,但我真的不知道它们是如何工作的。

template <class T>
T t[] = {1, "2"};

这给出了一个错误。我知道列表,但如果可能的话,我想使用数组。

【问题讨论】:

  • 您关于var 的说法是绝对错误的。 C# 中的var 是语法糖,它让编译器确定类型。它不是object
  • std::any/std::variant 或他们的 boost 同行
  • 出于好奇,你为什么需要那个?
  • 在 Java 中,任何类 Foo 隐式继承自 Object。 C++ 中没有这样的基础类型。
  • “但我真的很怀念 C++ 中的这一点” - 顺便说一句,如果你需要将你的对象称为 class Object 不止非常非常偶尔,那么你可能做错了。即使在Java

标签: java c# c++


【解决方案1】:

在 C# 中,可以通过引用标识的每个对象都以相同类型的标头开头,其中包括有关其类型的信息,它是否与监视器锁相关联等。这使得可以拥有可以使用的方法接收任何类型的引用并对由此识别的对象执行某些操作,而无需知道或关心引用的类型。

在 C++ 中,可能有没有任何标题的类型——只有原始数据。一些这样的类型称为 PODS(普通旧数据结构),可以支持一些其他类型无法安全完成的操作。但是,对于具有共同标头样式的对象,没有通用概念。即使许多非 PODS 类型确实支持至少一个需要某种标头的通用功能(检查基类指针是否可以安全地转换为派生类对象的能力),但不能保证标头包含足以唯一标识对象类别的信息。如果X1X2 都派生自X0,同样Z1Z2 派生自Z0,则实现可以简单地将0 存储在X0Z0 的标头中),1 代表X1Z1,2 代表 X2Z2。由于X0* 不可能识别Z1,而Z0* 无法识别X1,因此无需区分X1Z1 的标头。

由于没有可以唯一标识对象类型的标准标头,因此没有通用方法让函数接收指向任意未知类型对象的指针并对其执行任何有用的操作。

【讨论】:

  • 更有趣的是,尝试在没有指针的情况下在 C++ 中执行此操作是前往object slicing 的单程之旅。
  • 只有多态类型才支持验证从基类型转换为派生类型的安全性的系统,即使这样也只有在启用 RTTI 的情况下才支持。我不会把它算作非 POD 类型共享的“一个共同特征”。
  • @FrançoisAndrieux:我认为如果指针标识从基类型派生的任何对象,核心语言可以保证从基类型指针到特定派生类型指针的尝试强制转换是安全的。无论是否将其视为“共同特征”,我的意图是通过识别与此类特征最接近的事物并观察到即使这也不是什么特征来强调缺乏真实和有用的共同特征。跨度>
  • @supercat 这不适用于非polymorphic types。您的类层次结构中需要一个 virtual 成员函数。因此,c++ 中的许多类类型与 dynamic_cast 的使用不兼容。在某些情况下它仍然会成功,例如派生到基础的转换,但这些转换可以静态确定,不需要运行时信息。
  • @FrançoisAndrieux:我的主要观点是存在一类类型,C++ 必须为其包含某种标头,但它并不包括所有此类类型的标头,甚至在那些需要一个标头,它可能只能由知道期望什么基类的代码使用。这些特性共同排除了可以在类型不可知函数中使用各种对象的通用方法的可能性。
【解决方案2】:

这里有一小段 C++ 代码,可以满足您的要求。我想。 有时仅仅看一个例子是有帮助的。我认为网站 cppreference.com 是您的朋友。有很多很好的例子来说明用法。

#include <iostream>
#include <variant>
#include <array>

int main()
{
//  Note this will also work:
//  std::variant<int, std::string> t[] = { 1, "2" };

    using node = std::variant<int, std::string>; 
    std::array<node, 2> t = { 1, "2" };

    std::cout << "t[0]: " << std::get<int>(t[0]) << std::endl;
    std::cout << "t[1]: " << std::get<std::string>(t[1]) << std::endl;

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    相关资源
    最近更新 更多