如何用非虚函数覆盖虚函数?

问题描述 投票:4回答:4

参考此问题:Hide virtual function with non-virtual override

以及这个问题:override on non-virtual functions

覆盖虚拟函数的函数也是虚拟的,即使未显式声明为虚拟。

我的技术问题是:是否有必要使该替代函数成为非虚拟函数(并将其应用于层次结构中较低的类)?换句话说,我可以关闭“虚拟性”吗?

显然,我们可以使用虚函数覆盖非虚函数。我们可以做相反的事情,即用非虚函数覆盖虚函数吗?

c++ inheritance overriding virtual
4个回答
5
投票
您正在寻找一种替代虚拟功能的方法,以使其不再是虚拟的。

使用继承的可能方法

不幸的是,一旦成员函数被声明为虚拟的,就无法摆脱它的虚拟性。这是C ++标准的直接结果:

10.3 / 2:如果在Base类和从Base派生的类中声明了虚拟成员函数vf,

直接或间接派生

,具有相同名称的成员函数vf parameter-type-list,cv-qualification和refqualifier(或不存在)与Base :: vf是声明,然后Derived :: vf为也是虚拟使用final不会解决您的问题:它只会禁止您在更多派生类中重写该函数。该功能将保持虚拟状态。

但是,有一个(不方便的)技巧可以使用多重继承在一个特定级别上删除虚拟化:

class A { public: virtual void foo() { cout << "A" << endl; } }; class B : public A { public: void foo() { cout << "B" << endl; } }; class C : public B { public: void foo() { cout << "C" << endl; } }; class EH { // Helper class, does not derive from A public: // so foo() is non virtual here void foo() { cout << "EH!" << endl; } }; class E : public B, public EH { // inherits the virtual foo and the non virtual one public: using EH::foo; // We just say to use the non virtual one };

类E从虚拟和非虚拟继承。我们只是说要使用非虚拟的,如果有人调用它:

E e; e.foo(); // calls the non virtual function EH::foo(); => EH! B* pb2 = &e; pb2->foo(); // calls the original virtual function B::foo() => B

请注意,这个技巧

仅适用于当前级别

:如果您从E派生一个类,该类也会从A间接继承,这又是虚拟的诅咒!

您打算实现什么?

对于虚拟函数,无论您使用指向基数的指针如何,都确保始终调用与对象的真实身份相对应的适当函数。这就是多态性的目标。

使用非虚函数,编译器会根据您要访问的类型来调用他认为正确的函数。如果通过有效的基指针访问该对象,则它将使用基类的功能而不是派生的功能。这真的是您想要的吗?

如果是,请执行以下操作:

C c; B* pb = &c; pb->foo(); // uses the virtual function pb->B::foo(); // but you can force to use the function, ignoring the virtuality.

使用虚拟和非虚拟功能的可能方法

只需花费很少的额外费用,您就可以使用2种功能的组合在代码中模拟此行为:私有虚拟函数和公共非虚拟函数:

class A { virtual void foo2() { cout << "A" << endl; } // virtual function public: void foo() { foo2(); } // non virtual function calling the virtual one }; class B : public A { void foo2() { cout << "B" << endl; } // overriding virtual }; class C : public B { public: void foo() { cout << "C" << endl; } // ignore the virtual and override the non virtual function :-) };


2
投票
您想使用c ++ 11 final,类似:

1
投票
C ++引入了final。我没有用过,但这就是您的解决方案。该方法仍然是虚拟的,但是不能被覆盖。

1
投票
这里是我的技术回答,不,如果我们不重写派生类中的虚函数,那么派生类的vitable将包含基类虚函数的地址。
© www.soinside.com 2019 - 2024. All rights reserved.