因此,大型遗留代码库的结构看起来像这样。
我们有一个具有此公共(public)接口(interface)的基础应用程序:
// Base app
class BaseApp {
public:
...
Widget* getUiWidget(string _widgetName);
...
}
但是,我们的小部件是这样实现的
// Widget structure
class Widget {
...
}
class Button : public Widget {
...
}
class Label : public Widget {
...
}
问题无处不在我们的 View 代码中,我们有一堆如下所示的调用:
auto button = static_cast<Button*>(getUiWidget(buttonName));
if (button != nullptr) {
// something happens
button->doSomething1();
}
auto label = static_cast<Label*>(getUiWidget(buttonName));
if (label != nullptr) {
// something happens
label->doSomething2();
}
我个人不喜欢这样,因为实际上有数千个这样的电话,我觉得它可以做得更好。
我的直觉告诉我我可以做这样的事情
// Base app
class BaseApp {
public:
...
Widget* getUiWidget(string _widgetName);
Label* getLabel(string _labelName) {
if (//labelName is in widget layout)
return new NullLabel;
else
return new Label(_labelName)
}
Button* getButton(string _buttonName) {
if (//buttonName is in widget layout)
return new NullButton;
else
return new Button(_buttonName)
}
...
}
空对象在哪里
class NullButton : public Button {
public:
// override all methods of button and do nothing with it
}
class NullLabel : public Label {
public:
// override all methods of Label and do nothing with it
}
所以代码:
auto button = static_cast<Button*>(getUiWidget(buttonName));
if (button != nullptr) {
// something happens
button->doSomething();
}
// Would turn in to
auto button = getButton(buttonName);
button->doSomething1();
我对这种方法的问题是,我们有 n 个小部件子级,例如切换、 slider 等。因此,为了实现此目的,我需要 n 个 getSomeWidgetChild
并且我也会需要写入n个NullSomeWidgetChild
。
有更好的解决方案吗?
最佳答案
可以使用访问者模式来避免动态强制转换。 (问题中标记的静态转换是危险的!)
- 在小部件层次结构中定义新的接受方法。
- 创建一个新的访问者类,其中包含您想要在重载访问函数中执行的所有特定于对象的“执行某些操作”。
添加访问者类别:
class Visitor {
public visit (Button* button) { /* do button specific work */}
public visit (Label* label) { /* do label specific work */}
}
添加接受方法:
// Widget structure
class Widget {
virtual public accept (Visitor * v);
...
}
class Button : public Widget {
public accept (Visitor * v) override {v->visit(this);}
...
}
class Label : public Widget {
public accept (Visitor * v) override {v->visit(this);}
...
}
现在您的代码将更改为:
Visitor* v = new Visitor;
auto button = getUiWidget(buttonName);
button.accept(v);
关于c++ - 如何避免 C++ 中的许多静态强制转换和 nullptr 检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47800316/