2

该应用程序定义了 3 个要在插件中实现的接口。Widget永远是基础。

// Application code...
class Widget {
    virtual void animate() = 0;
};

class BigWidget : public Widget {
};

class SmallWidget : public Widget {
};

每个接口实现都派生自NiceWidget其中,提供了一些插件内部的公共信息。

// Plug-in code...
class NiceWidget {
    // nice::Thing is only known in plug-in code.
    nice::Thing thing();
};

class NiceBigWidget : public NiceWidget, public BigWidget {
    void animate() override;
};

class NiceSmallWidget : public NiceWidget, public SmallWidget {
    void animate() override;
};

func从应用程序代码中调用。wid已知由该插件实现。因此 wid 也是一个NiceWidget. 的目标func是调用thing它的方法。

// Plugin-in code...
void func(Widget* wid) {
    // wid is either NiceBigWidget or NiceSmallWidget.
    auto castedBig = dynamic_cast<NiceBigWidget*>(wid);
    if (castedBig) {
        castedBig->thing().foo();
        return;
    }

    auto castedSmall = dynamic_cast<NiceSmallWidget*>(wid);
    if (castedSmall) {
        castedSmall->thing().foo();
        return;
    }

    assert(false);
}

但是随着层次结构大小的增加,尝试对wid每个人都进行强制转换会变得非常糟糕。Nice*有更好的解决方案吗?

4

2 回答 2

3

第一:如果你知道那wid将永远是一个NiceWidget*,为什么不在 中这么说呢func()?而且您根本不需要演员表:

void func(NiceWidget* wid)
{
  wid->thing().foo();  // Done
}

即使您出于某种原因无法更改函数签名,您也只需要一次强制转换:

void func(Widget* wid)
{
  NiceWidget* casted = dynamic_cast<NiceWidget*>(wid);
  if (casted)
    casted->thing().foo();
  else
    throw std::exception(); // Well, throw the right exception
}

当然,如果您认为它更适合您的目的,您可以assert()代替抛出异常。

在任何情况下,您只需要一个指向定义您需要使用的函数的类的指针(在本例中为thing()),而不是指向最派生类的指针。如果您将在派生类中覆盖该函数,请将其设为虚拟,无论如何您都完成了。

于 2013-01-03T16:41:35.753 回答
0

如果您知道,every NiceWidgetis Widget,您应该考虑NiceWidget从扩展Widget

class Widget {
    virtual void animate() = 0;
};

class BigWidget : public Widget {
};

class SmallWidget : public Widget {
};

class NiceWidget : Widget{
    // nice::Thing is only known in plug-in code.
    nice::Thing thing();
};


class NiceBigWidget : public NiceWidget, public BigWidget {
    void animate() override;
};

class NiceSmallWidget : public NiceWidget, public SmallWidget {
    void animate() override;
};

还有一个问题叫做菱形问题,可以用虚扩展来解决。

之后dynamic_castWidget到应该没问题NiceWidget

于 2013-01-03T16:42:15.350 回答