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

时间:2015-02-19 12:52:44

标签: c++ inheritance override virtual

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

这个问题:override on non-virtual functions

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

我的技术问题是:是否存在将该重写函数设置为非虚拟(并将其应用于层次结构中较低的类)?换句话说,我可以转变"虚拟"关闭?

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

4 个答案:

答案 0 :(得分:3)

您正在寻找一种覆盖虚拟功能的方法,以使其不再是虚拟功能。

使用继承的可能方法

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

  

10.3 / 2:如果虚拟成员函数vf在类Base和Derived类中声明,直接或间接从Base派生,   一个具有相同名称的成员函数vf,parameter-type-list,   与Base :: vf相关的cv-qualification和refqualifier(或不存在)   声明,然后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 :-) 
};

答案 1 :(得分:1)

您想要使用c ++ 1 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
};

答案 2 :(得分:0)

C ++引入了final。我没用过它,但这是你的解决方案。该方法仍然是虚拟的,但无法覆盖。

答案 3 :(得分:0)

这是我的技术答案否,如果我们不覆盖派生类中的虚函数,那么派生类的vitable将包含基类虚函数的地址。