1

我正在尝试创建一个实际上类似于 Python 对象的list对象。在我的代码中,我有以下类:object_type, type_type, none_type, bool_type, int_type, float_type, ,抽象类bytes_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并具有其虚函数。

你有什么想法?我很高兴听到你的建议。

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

4

2 回答 2

1
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<object_type*>。它的类型是object_type*. 您应该返回object_type*object_type&。这些是可能的最佳返回类型。C++ 类型系统不够复杂,无法让函数的返回类型取决于其输入。

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

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

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

于 2013-01-06T16:02:15.553 回答
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 类似于这个想法,所以你可以看看他们是如何实现的。

于 2013-01-06T13:50:12.430 回答