下播最佳实践(C++)

Downcasting best-practice (C++)

本文关键字:C++ 最佳      更新时间:2023-10-16

静态代码分析工具往往会漫无边际地谈论"将基类下转换为派生类",我还发现了一些编码标准指南,其中提到了不要这样做,所以我想知道什么是最佳实践方式。

这是我的用例:

我有一个Base(接口)、DerivedA、DerivedB类,然后是一个包含Base指针的数组。

然后,我在数组中迭代,并根据一个标志,确定对象是DerivedA还是DerivedB,将其向下转换,然后从外部对对象执行一些随机操作。

基本上是这样的:

// arr is of type Base**
for (int i = 0; i < size; ++i)
{
// doMagic has an overload for both types
if (arr[i]->isDerivedA())
{
doMagic(reinterpret_cast<DerivedA*>(arr[i]));
}     
else if (arr[i]->isDerivedB())
{
doMagic(reinterpret_cast<DerivedB*>(arr[i]));
}
}

除了重新解释之外,由于嵌入式平台的限制(C++11也是如此),我不能使用dynamic_cast,但基类作为接口保证了对象是DerivedA或DerivedB。

我可以让DerivedA和DerivedB只实现纯虚拟调用,因此我不必担心下转换任何东西,但DerivedA和DerivedB类非常专业,doMagic对实例做完全不同的事情。。。

所以我想知道你们是如何做到这一点的——拥有一个由非常不同的对象组成的数组,但从一个基继承,在它们之间迭代,并从外部做一些专门的事情。

您可能应该尝试使用访问者模式。这里有一个简单的例子:

#include <cstdio>
class A;
class B;
class Visitor {
public:
void visit(A &a) {
printf("Visited An");
}
void visit(B &) {
printf("Visited Bn");
}
};

class A {
public:
virtual ~A() { }
virtual void applyVisitor(Visitor &v) {
v.visit(*this);
}
};
class B : public A {
public:
~B() override { }
void applyVisitor(Visitor &v) override {
v.visit(*this);
}
};

int main() {
A a;
B b;
Visitor v;
a.applyVisitor(v);
b.applyVisitor(v);

return 0;
}

如果知道基类的指针指向派生类的对象,则可以使用static_cast。编译器将插入适当的代码来调整偏移量,这与reinterpret_cast或C-cast不同。