如果我必须覆盖非虚拟成员函数怎么办

What if I must override a non-virtual member function

假设我们有一个库提供了 class

struct Base { int foo() { return 42; } };

我无法更改 class。 99% 的人永远不想覆盖 foo,因此它没有被库设计者虚拟化。 但我需要覆盖它:

struct MyClass : Base { int foo() { return 73; } };

更糟糕的是,该库的接口接受指向 Base 的指针。 我想插入MyClass,当然,由于foo不是虚拟的,接口后面的代码总是调用Base::foo我想让它调用 MyClass::foo.

我该怎么办? 是否有通用模式可以使 Base::foo 看起来像虚拟的?

实际上,Base::fooQAbstractProxyModel::sourceModel。 我正在实施 ProxyChain,将许多代理模型抽象为一个。 QAbstractProxyModel::setSourceModel 是虚拟的,但 QAbstractProxyModel::sourceModel 不是,这会带来很多麻烦。

void ProxyChain::setSourceModel(QAbstractItemModel* source_model)
{
  for (auto* proxy : m_proxies) {
    proxy->setSourceModel(source_model);
    source_model = proxy;
  }
  QIdentityProxyModel::setSourceModel(source_model);
}

QAbstractItemModel* ProxyChain::sourceModel() const
{
  return m_proxies.front()->sourceModel();
}

What can I do about it?

没有。

这就是为什么如果我们希望其他人能够 "pretend" 他们的 类 是我们 类 的版本,那么指南告诉我们使用 virtual 的原因。

Base的作者没有那样做,所以你没有那个权力。

就是这样。

What can I do about it?

没有。如果一个成员函数是非virtual,那么它就是非virtual。这意味着代码库中任何地方的任何代码,如果采用 Base 指针或调用 base->foo 的引用,将准确且仅调用 Base::foo。此调用静态(编译时)绑定到它调用的函数。

您无法访问其他人的代码,他们使用动态绑定。如果他们没有选择参与动态绑定,那么你就无法制作他们。您可以创建自己的派生 class 并编写自己的 foo 版本,它隐藏了基础 class 版本。但这不会影响任何从 pointer/reference 到 Base.

的代码的行为

在您的具体情况下,您最好的选择是确保使用您想要的对象调用基 class setSourceModel sourceModel 到 return any时间发生了一些变化,这改变了 sourceModel 应该 return.

的东西