Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override a virtual function with a non-virtual function?

Refer to this question: Hide virtual function with non-virtual override

And this question: override on non-virtual functions

A function that overrides a virtual function is virtual too, even though it's not explicitly declared virtual.

My technical question is: Is there away to make that overriding function non-virtual (and applies that to classes lower in the hierarchy)? In other words, can I turn the "virtuality" off?

Obviously we can override a non-virtual function with a virtual function. Can we do the opposite, i.e. to override a virtual function with a non-virtual function?

like image 491
Tris Avatar asked Feb 19 '15 12:02

Tris


People also ask

Can I override a non-virtual function?

You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.

Can we override virtual as well as non-virtual methods?

By default, methods are non-virtual, and they cannot be overridden. Virtual modifiers cannot be used with static, abstract, private, and override modifiers.

Is it possible to override a method which is declared without a virtual keyword?

No, you cannot override a non-virtual method.

Can virtual methods be overridden?

A virtual inherited property can be overridden in a derived class by including a property declaration that uses the override modifier.


2 Answers

You are looking for a way to overrride a virtual function, so that it is no longer virtual.

Possible approaches using inheritance

Unfortunately, you cannot get rid of the virtuality of the member function once it is declared virtual. This is a direct consequence of the C++ Standard:

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.

The use of final will not solve your problem: it will just forbid you to override the function in more derived classes. The function will remain virtual.

There is however an (unconvenient) trick to remove virtualisation at one specific level, using multiple inheritance:

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
};

The class E inherits from both the virtual and the non virtual. We just say to use the non virtual one if one calls it:

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

Be aware that this trick works only for the current level: If you'd derive a class form E, the class would also inherit indirectly from A, and here is the virtual curse again !

What do you intend to achieve ?

With virtual functions, you ensure that you always call the appropriate function corresponding to the real idendity of your object, regardless the fact that you use a pointer to a base. That's the goal of polymorphism.

With non-virtual function, your compiler invokes the function he thinks is the correct one, according to the type you are accessing to. If you access the object via a valid base pointer it will hence use the function of the base class instead of the derived one. Is this really what you want ?

if yes, just do this:

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.  

Possible approach using a virtual and a non virtual function

With little additional cost you could emulate this behaviour in your code, using a comibnation of 2 functions: a private virtual one, and a public non virtual:

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 :-) 
};
like image 68
Christophe Avatar answered Sep 23 '22 20:09

Christophe


C++ introduced final. I've not used it, but that's your solution. The method is still virtual but it can't be overridden.

like image 34
Cheers and hth. - Alf Avatar answered Sep 24 '22 20:09

Cheers and hth. - Alf