在运行时强制转换为派生类型
Casting to derived type during Runtime
假设我有 3 个类指针 classA、Class B 和 ClassC 所有这些类都派生自 QObject。我想知道是否有办法让我从基本类型中找出他们的派生类型是什么。例如,如果我有这样的东西
void SomeMethod(QObject* ptr)
{
//How can I find out if a ClassA , ClassB or ClassC derived type was passed here ?
}
dynamic_cast
的用途:
void SomeMethod(QObject *ptr) {
A *a = dynamic_cast<A *>(ptr);
if (a) { DoStuffA(a); return; }
B *b = dynamic_cast<B *>(ptr);
if (b) { DoStuffB(b); return; }
C *c = dynamic_cast<C *>(ptr);
if (c) { DoStuffC(c); return; }
DoStuffNOTA(ptr);
}
由于您使用的是Qt,因此您可能希望使用qobject_cast
而不是dynamic_cast
,*但除此之外一切都是一样的。
然而,像往常一样,所有这些重复都是你做错了什么的迹象。您可以使用模板消除很多内容,但通常,您通常根本不想这样做。请改用"双重派送"(又名"反向派送")模式。
我们有虚函数和一般的OO的全部原因是为了避免类型切换。问题是虚函数(C++的方式)只调度this
对象:Foo::SomeMethod(QObject *)
可以覆盖Foo
的子类,但不能覆盖QObject
的子类。但是,您只需添加一个方法来QObject
- 或者,在这种情况下,添加到一个中间类(或多继承混合,如果不可能的话) - 所有实际类都可以重写:
class ClassIntermediate: public QObject {
public:
virtual void DoSomeMethodStuff() = 0;
};
class ClassA : public ClassIntermediate {
public:
virtual void DoSomeMethodStuff() { /* DoStuffA code here */ }
// all the stuff you were already doing in ClassA as a QObject
};
// likewise for ClassB and ClassC
class Foo {
void SomeMethod(ClassIntermediate *ptr) { ptr->DoSomeMethodStuff(); }
};
如果必须为所有类型的类型完成一些工作,请将其保留在 SomeMethod
中,在调用 DoSomeMethodStuff
之前或之后。(如果该工作与特定于子类的内容混合在一起,并且您无法重新排列它,只需分解出多个方法进行双重调度,而不仅仅是一个。
如果代码需要 Foo
对象的this
指针,只需将其作为参数传递给 DoSomeMethodStuff
。
如果你需要处理任何QObject
,而不仅仅是你的子类,那么你可能需要使用单个dynamic_cast<ClassIntermediate *>
并对此进行双重调度。
那么,为什么这比类型切换更好呢?今天,您有三个类,以及一个打开它们的方法。如果明天添加另一个方法,则必须再次编写相同的 3 路类型开关。如果随后添加第四个类,则必须记住返回并编辑它们。如果你最终得到 N 个类和 M 个必须打开它们的方法,那么你已经编写了 N*M 个代码块而不是 N+M。所有这些额外的代码不仅令人讨厌;它几乎可以保证您有一天会错过其中一次编辑,从而导致痛苦的调试问题。
qobject_cast
的主要优点是Qt提供了自己的,比C++内置的更广泛的RTTI系统,并且可以在完全没有C++RTTI的情况下构建Qt(或者,在Windows上,以这样一种方式,不同DLL中的类可以通过Qt RTTI连接,但不能C++RTTI), qobject_cast
仍然有效。
- 在 C++ 中用派生类型重写成员函数
- 在 C++ 中将对象转换为派生类型
- C++如果采用类类型的函数被传递派生类型,有没有办法给出错误?
- 返回派生类型时出现协变类型错误
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- 基于派生类型的编译时行为分支
- 按类型排序向量并按类型或派生类型搜索
- 为什么"运算符<<"不适用于指向派生类型的成员?
- 无法返回派生类型的标准::unique_ptr<>
- 无法从派生类型的作用域访问另一个实例的受保护成员
- dynamic_cast到具有未知模板参数的派生类型
- 派生类型的成员
- 视觉C++ dynamic_cast返回 NULL,尽管对象是派生类型
- 在运算符中动态强制转换为派生类型<<
- 如何在不转换回基类类型的情况下返回派生类型的对象?
- 将派生指针分配给C 中的其他派生类型
- 如何将派生类型的对象放在用于基本类型的向量中
- C++ - 无法将派生类型作为基类型列表传递给构造函数
- 如何在基本类型参考中存储对派生类型的参考
- 统一处理具有协变类型的函数指针(如何使用派生类型调用回调?