如果我必须覆盖非虚拟成员函数怎么办
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::foo
是 QAbstractProxyModel::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.
的东西
假设我们有一个库提供了 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::foo
是 QAbstractProxyModel::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.