c++ - 如何避免 C++ 中的许多静态强制转换和 nullptr 检查?

标签 c++ algorithm design-patterns

因此,大型遗留代码库的结构看起来像这样。

我们有一个具有此公共(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

有更好的解决方案吗?

最佳答案

可以使用访问者模式来避免动态强制转换。 (问题中标记的静态转换是危险的!)

  1. 在小部件层次结构中定义新的接受方法。
  2. 创建一个新的访问者类,其中包含您想要在重载访问函数中执行的所有特定于对象的“执行某些操作”。

添加访问者类别:

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/

相关文章:

c++ - 在 C 或 C++ 中实现 Prolog

algorithm - 非对称 key 加密算法如何保持单向解密和加密功能?

class - 工厂设计模式和管道设计模式有什么区别?

c# - 在 C# 中,如何正确实现命令设计模式?

c++ - Qt C++ : Moving a file, 源路径和目标路径在不同的驱动器上

c++ - 快速检查号码是大号码的倍数

c - 在给定邻接图和多次遍历的情况下优化方法以找到遍历最多的边

java - 二维数组深度优先搜索

java - 保持内存中更改与后端同步的好方法是什么

c++ - 内存泄漏,窗口是否有防止达到最大内存的保护措施?