【问题标题】:c++: Python's list analoguec++:Python 的列表类比
【发布时间】:2012-12-20 06:58:32
【问题描述】:

我正在尝试创建一个实际上类似于 Python 的 list 对象的对象。在我的代码中,我有以下类:object_typetype_typenone_typebool_typeint_typefloat_typebytes_type,其中object_type 是抽象类。

抽象类有一些虚函数,如type_type __type__(void)bytes_type __name__(void)bytes_type __repr__(void)bool_type __bool__(void)int_type __int__(void)float_type __float__(void)bytes_type __bytes__(void)

type_type 类具有以下构造函数:type_type(object_type*);在构造过程中,指向源对象的指针存储到object_type* type_type::__cdata__,当用户想要使用type_type::__eq__(const type_type&)函数比较两种类型时使用(这个函数使用typeid,你可能已经猜到了)。

我需要创建list_type 对象,它可以存储任何基于object_type 的对象。它必须有__get__(const int_type&) 函数来获取元素和__set__(const int_type&, object_type*) 函数来设置元素。所有对象都存储在std::vector<object_type*> __cdata__中。

如何强制list_type::__get__(const int_type&) 返回正确的对象?假设我们有list_type,它包含三个元素:[bytes_type object0, int_type object1, float_type object3]。使用list_type::__get__(0) 应该返回bytes_type object0。可能函数type_type object_type::__type__() 会很有用。

用户可以在执行期间创建基于object_type 的新类型存在困难(我所描述的所有内容都用于创建新的玩具语言)。但是所有类型都基于object_type 并具有其虚函数。

你有什么想法吗?我很乐意听取您的建议。

附: git仓库:https://github.com/ghostmansd/quirinus

【问题讨论】:

  • 你还没有说list_type::get(n) 应该返回什么。第n个元素? n 型的第一个元素?什么?
  • “用户可以在执行期间创建一个新的 [...] 类型”——如何?
  • @BenjaminLindley:名称的使用方式与 Python 中使用的方式相同。这只是实现。
  • @n.m.:我写过我现在尝试创建一种新的玩具语言。但我想以后我可以添加创建新类的可能性。

标签: c++ arrays types vector type-conversion


【解决方案1】:

您在方法中使用的方法约定非常类似于 python。正如@BenjaminLindley 所说,这是无效的,因为在 C++ 中,以双下划线为前缀的名称保留给编译器(在 Python 中,它们保留用于 __eq__ 等特殊方法,但在 C++ 中,您可以重载 == 以获得类似的效果)。

注意:以下适用于编译时已知的类型。

由于 C++ 是静态类型的,因此您不能返回多种类型。您必须返回 object_type& ,然后可以将其转换回原始类型:

您的列表可以存储(智能)指向 object_type 的指针,并且您的 get 方法(或重载的 [] 运算符)将返回对 object_type 的引用。

// data is underlying container of pointers, getInt() returns int value from int_type
object_type& get(const int_type& i) { return *(data[i.getInt()]); }

这里使用引用来避免切片并访问存储在列表中的值。

用户必须进行强制转换才能获得对象的原始类型。

try
{
    bytes_type& object0 = dynamic_cast<bytes_type&>(your_list.get(0))
    // operate on object0
}
catch(std::bad_cast& e)
{
     // type was incorrect
     std::cout << "Invalid type";
}

boost::any 类似于这个想法,所以你可以看看他们是如何实现的。

【讨论】:

    【解决方案2】:
    All objects are stored inside std::vector<object_type*> __cdata__.
    
    How can I force list_type::__get__(const int_type&) to return correct object?
    

    std::vector&lt;object_type*&gt; 中已经有正确的对象。它的类型是object_type*。您应该返回object_type*object_type&amp;。这些是可能的最佳返回类型。 C++ 类型系统不够复杂,无法让函数的返回类型取决于其输入。

    您应该考虑使用智能指针而不是原始指针,但原则保持不变。

    附注。 您可以使用指向object_type 的引用或指针(智能或原始)做什么?两件事:您可以将其转换为其他指针或引用,或者您可以通过它调用虚函数。强制转换只有在您知道或可以猜测目标类型的情况下才有用,并且通过虚函数实现每个可以想象的操作是不切实际的,因为存在无限的可想象操作集。这可能意味着这个设计不是你想做的最好的。

    哦,你不应该在 C++ 中使用双下划线。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-09
      • 1970-01-01
      • 2021-02-19
      • 2023-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多