【发布时间】:2020-05-27 18:10:40
【问题描述】:
想象以下场景。我从一个库类派生来启用访问者模式:
#include <iostream>
#include <vector>
struct MyClassA;
struct MyClassB;
struct MyVisitor{
virtual void visit(MyClassA* c) { std::cout << "My Class A" << std::endl; }
virtual void visit(MyClassB* c) { std::cout << "My Class B" << std::endl; }
};
struct LibClass {};
struct MyClass : public LibClass {
virtual void Accept(MyVisitor& visitor) = 0;
};
struct MyClassA : public MyClass {
virtual void Accept(MyVisitor& visitor) {
visitor.visit(this);
}
};
struct MyClassB : public MyClass {
virtual void Accept(MyVisitor& visitor) {
visitor.visit(this);
}
};
// vector signature can't be changed
void foo(std::vector<LibClass*>& v) {
MyVisitor visitor;
for(auto libC : v) {
auto myC = static_cast<MyClass*>(libC); // questionable line
//auto myC = dynamic_cast<MyClass*>(libC); // don't want to use dynamic cast
myC->Accept(visitor);
}
}
int main() {
// vector signature can't be changed
std::vector<LibClass*> v;
v.push_back(new MyClassA());
v.push_back(new MyClassB());
foo(v);
return 0;
}
输出如预期:
My Class A
My Class B
这是一个关于设计的问题。在我看来,使用dynamic_cast 是不好的风格,应该避免使用。由于向量可能会变得很大,我还想避免在迭代中调用dynamic_cast。
我可以肯定,向量中的每个指针都派生自MyClass。
我想使用访问者模式来实现依赖于派生类的特性,所以我也会实现MyVisitor的派生类。 MyVisitor 以后可以为所有可能的孩子提供一个虚拟接口。具体的访问者只能覆盖他们想要与之交互的孩子的方法。
所以我的问题是:
- 这样使用
static_cast有什么危险吗? - 在我想插入使用访问者模式的可能性的情况下,您认为这是一个好的设计吗?
【问题讨论】:
-
“在我看来,使用
dynamic_cast是不好的风格,应该避免使用。” ——你还没有解释为什么你认为(有原因,但其中一些同样适用于static_cast)。 -
@KonradRudolph 在我的代码中这将是不好的风格,因为我会误用 dynamic_cast 作为开关。 (因为如果我使用 dynamic_cast,我根本不需要访问者)我想使用访问者来区分类型而不是 RTTI(或 dynamic_cast)
标签: c++