类型发现¶
当从指向基类的指针转换属于类层次结构的对象时,期望获得实际的最派生类型的Python类型,这与C++不同,C++需要为此进行类型转换:
def event(self, event):
if event.type() == QEvent.Type.MousePress:
self.do_things(event.position())
...
bool event(QEvent *event) override
{
if (event->type() == QEvent::MousePress) {
auto *mouseEvent = static_cast<QMouseEvent *>(event);
doThings(mouseEvent->position());
...
}
确定事件类型的过程称为类型发现。
Shiboken 生成代码以自动检测类型。首先,它尝试为通过 typeid(*pointer).name() 获得的名称找到一个转换器。这通常应该有效,因为该名称由绑定注册。如果失败,它开始遍历在 libshiboken 中构建的类型继承图,通过使用转换函数(默认情况下为 dynamic_cast<>)来检查并找到最派生的类。
对于具有虚析构函数的普通类层次结构,通常不需要特殊处理,因为typeid()通常会检测到正确的类名。
多重继承¶
在C++的多重继承情况下,如果不是单行直接继承,则不会进行到派生类的转换。例如,在Qt中,类QWidget同时继承了QObject(QObject层次结构的基类)和QPaintDevice。
当调用一个返回QPaintDevice *的函数时,例如
QPainter.device(),返回的是一个表示QPaintDevice的Python类型,
而不是底层的小部件类型。这个限制存在是因为
C++中的底层指针是一个指向QPaintDevice *的指针,并且与
指向QWidget的指针不同。
具有非虚析构函数的类层次结构¶
有一些具有层次结构的C++类没有虚析构函数。这使得基于typeid()和dynamic_cast<>的类型发现变得不可能。
Qt中的示例是QStyleOption派生的或QGradient派生的类。
对于这些类,需要在类型条目上指定一些属性:
首先,必须指定一个polymorphic-id-expression属性,用作替换dynamic_cast<>的检查。
此外,可以指定一个polymorphic-name-function属性。
这取代了通过typeid()获得的类型名称猜测,主要是为了通过跳过继承图中每种类型的检查来加快速度。
一个polymorphic-base属性标识了层次结构的基类。在基类继承自另一个类的情况下,应提供此属性以防止逻辑深入到基类以下。
使用类型发现属性为具有虚拟析构函数的类层次结构¶
可以使用polymorphic-id-expression和
polymorphic-name-function来处理具有虚析构函数的普通类层次结构,因为它们基本上取代了typeid()和
dynamic_cast<>。如果能够指定比虚表检查更快的表达式,这样做是有意义的。
指定polymorphic-base在多重继承的情况下生成特殊的转换函数也是有意义的。例如,在Qt中,QWindow、QLayout、QWidget是层次结构的基类。由于它们都继承自QObject,指定基类可以防止逻辑使用QObject作为基类。
类型发现属性参考¶
以下与类型发现相关的属性可以在 object-type 或 value-type 元素上指定:
多态ID表达式¶
polymorphic-id-expression 属性指定了一个表达式,用于检查基类指针是否匹配特定类型。例如,在 virtual eventHandler(BaseEvent *e) 函数中,此属性用于构建与派生类(例如 MouseEvent 或类似类)匹配的 Python 包装器。属性值可能包含占位符:
- %1
完全限定的类名
- %B
基类的完全限定名称(通过基类搜索找到或由polymorphic-base指示)。
要检查继承BaseEvent的类,请指定:
<object-type name="MouseEvent"
polymorphic-id-expression="%B->type() == BaseEvent::MouseEvent"/>
多态名称函数¶
polymorphic-name-function 属性指定了一个函数的名称,该函数在基类类型条目上返回派生类的类型名称。通常,typeid(ptr).name() 用于此目的。
该函数预计返回 const char *。
多态基础¶
布尔属性 polymorphic-base 表示该类是否为类层次结构的基类。它用于 polymorphic-id-expression 中的 %B 占位符以及多重继承中的类型转换操作。