如何用非虚函数覆盖虚函数?
How to override a virtual function with a non-virtual function?
参考这个问题:Hide virtual function with non-virtual override
还有这个问题:override on non-virtual functions
覆盖虚函数的函数也是虚函数,即使它没有明确声明为虚函数。
我的技术问题是:是否可以使该覆盖函数成为非虚拟函数(并将其应用于层次结构中较低的 类)?换句话说,我可以关闭 "virtuality" 吗?
显然我们可以用虚函数覆盖非虚函数。我们可以做相反的事情,即用非虚函数覆盖虚函数吗?
引入了 C++ final
。我没有使用过它,但这是您的解决方案。该方法仍然是虚拟的,但不能被覆盖。
您想使用 c++11 final
,类似于:
struct A {
virtual void foo();
};
struct B : A {
void foo() final; // virtual overrides A::foo
};
struct C : B {
void foo(); // error: can't override
};
您正在寻找一种方法来覆盖虚函数,使其不再是虚函数。
使用继承的可能方法
不幸的是,成员函数一旦声明为虚函数,就无法摆脱它的虚函数。这是 C++ 标准的直接结果:
10.3/2: If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base,
a member function vf with the same name, parameter-type-list ,
cv-qualification, and refqualifier (or absence of same) as Base::vf is
declared, then Derived::vf is also virtual.
使用 final
不会解决您的问题:它只会禁止您在更派生的 class 中重写该函数。该功能将保持虚拟。
然而,有一个(不方便的)技巧可以使用多重继承在一个特定级别删除虚拟化:
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
};
classE同时继承了虚拟和非虚拟。我们只是说如果有人调用它就使用非虚拟的:
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
请注意,此技巧仅适用于当前级别:如果您派生出 class 形式 E,则 class 也将继承间接来自 A,这里又是虚拟诅咒!
你打算达到什么目标?
使用虚函数,您可以确保始终调用与对象的真实身份相对应的适当函数,而不管您使用的是指向基的指针这一事实。这就是多态性的目标。
对于非虚函数,您的编译器会根据您要访问的类型调用他认为正确的函数。如果您通过有效的基指针访问对象,它将因此使用基函数 class 而不是派生函数。这真的是你想要的吗?
如果是,就这样做:
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 个函数的组合:一个私有虚拟函数和一个 public 非虚拟函数:
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 :-)
};
这是我的技术答案 不,如果我们不覆盖派生 class 中的虚函数,那么派生 class 的 vitable 将包含基地址 class 虚函数.
参考这个问题:Hide virtual function with non-virtual override
还有这个问题:override on non-virtual functions
覆盖虚函数的函数也是虚函数,即使它没有明确声明为虚函数。
我的技术问题是:是否可以使该覆盖函数成为非虚拟函数(并将其应用于层次结构中较低的 类)?换句话说,我可以关闭 "virtuality" 吗?
显然我们可以用虚函数覆盖非虚函数。我们可以做相反的事情,即用非虚函数覆盖虚函数吗?
引入了 C++ final
。我没有使用过它,但这是您的解决方案。该方法仍然是虚拟的,但不能被覆盖。
您想使用 c++11 final
,类似于:
struct A {
virtual void foo();
};
struct B : A {
void foo() final; // virtual overrides A::foo
};
struct C : B {
void foo(); // error: can't override
};
您正在寻找一种方法来覆盖虚函数,使其不再是虚函数。
使用继承的可能方法
不幸的是,成员函数一旦声明为虚函数,就无法摆脱它的虚函数。这是 C++ 标准的直接结果:
10.3/2: If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list , cv-qualification, and refqualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual.
使用 final
不会解决您的问题:它只会禁止您在更派生的 class 中重写该函数。该功能将保持虚拟。
然而,有一个(不方便的)技巧可以使用多重继承在一个特定级别删除虚拟化:
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
};
classE同时继承了虚拟和非虚拟。我们只是说如果有人调用它就使用非虚拟的:
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
请注意,此技巧仅适用于当前级别:如果您派生出 class 形式 E,则 class 也将继承间接来自 A,这里又是虚拟诅咒!
你打算达到什么目标?
使用虚函数,您可以确保始终调用与对象的真实身份相对应的适当函数,而不管您使用的是指向基的指针这一事实。这就是多态性的目标。
对于非虚函数,您的编译器会根据您要访问的类型调用他认为正确的函数。如果您通过有效的基指针访问对象,它将因此使用基函数 class 而不是派生函数。这真的是你想要的吗?
如果是,就这样做:
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 个函数的组合:一个私有虚拟函数和一个 public 非虚拟函数:
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 :-)
};
这是我的技术答案 不,如果我们不覆盖派生 class 中的虚函数,那么派生 class 的 vitable 将包含基地址 class 虚函数.