如果我必须覆盖非虚拟成员函数怎么办
What if I must override a non-virtual member function
假设我们有一个提供类的库
struct Base { int foo() { return 42; } };
我无法更改该类。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();
}
我能做些什么呢?
无。
这就是为什么指南告诉我们,如果我们希望其他人能够"假装"他们的类是我们类的版本,请使用virtual
。
Base
的作者没有这样做,所以你没有那个权力。
就是这样。
我能做些什么呢?
无。如果一个成员函数是非virtual
,那么它是非virtual
。这意味着代码库中任何位置的任何代码,如果采用Base
指针或引用谁调用base->foo
,将完全调用并且仅Base::foo
。此调用静态(编译时(绑定到它调用的函数。
您不能访问其他人的代码并让他们使用动态绑定。如果他们没有选择参与动态绑定,那么你就不能制作他们。您可以创建自己的派生类并编写自己的foo
版本,以隐藏基类版本。但这不会影响任何获得指向Base
的指针/引用的代码的行为。
在特定情况下,最好的办法是确保使用您希望sourceModel
在更改时返回的对象调用基类setSourceModel
,从而更改sourceModel
应该返回的内容。
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 如果我必须覆盖非虚拟成员函数怎么办
- 非虚拟成员函数是否可以使用模板参数?
- 如何将已实现的虚拟成员函数作为参数传递
- 睡眠影响 std::thread 调用哪个虚拟成员函数?
- GTEST:嘲笑非虚拟成员函数
- 虚拟和非虚拟成员函数的调用方式有什么区别?
- 默认情况下是虚拟成员函数
- 为什么在已删除的指针上调用非虚拟成员函数是未定义的行为
- C++标准是否保证了没有虚拟成员函数的类类型的大小
- 在非构造"object"上调用非虚拟成员函数是否定义良好?
- 指向虚拟成员函数的指针是否具有可比性
- 通过指针访问私有虚拟成员函数
- 如何获取"direct"函数指向虚拟成员函数的指针?
- 将 decltype 与虚拟成员函数指针一起使用
- 如何使用基类指针调用派生类非虚拟成员函数,而无需类型转换和使用多态性
- 如何清理已由虚拟成员函数分配的资源
- 具有函数体的纯虚拟成员函数的意义何在
- 在现代CPU中,虚拟成员函数对局部性是好是坏
- 将指向虚拟成员函数的指针作为普通C函数的参数传递