How to Override a Non-Virtual Method

Overriding non-virtual methods

Yep, you are misunderstanding a little.

The method of the same name on the derived class will hide the parent method in this case. You would imagine that if this weren't the case, trying to create a method with the same name as a base class non-virtual method should throw an error. It is allowed and it's not a problem - and if you call the method directly as you have done it will be called fine.

But, being non-virtual, C++ method lookup mechanisms that allow for polymorphism won't be used. So for example if you created an instance of your derived class but called your 'Display' method via a pointer to the base class, the base's method will be called, whereas for 'vDisplay' the derived method would be called.

For example, try adding these lines:

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

...and observe the output as expected:

Base: Non-virtual display.

Base: Virtual display.

Base: Non-virtual display.
Derived: Virtual display.

Can i use a method overriding a non-virtual method?

Is there a point to override a non-virtual method?

You are not actually overriding, but this is the behavior, i.e

B* b = new B();
A* a = new B();
b->method(); //Calls B's method
a->method(); // Calls A's method

So, the pointer/reference type determines the method called.

can i create an instance of B and somehow use the method defined in B?

Yes. The pointer/reference type has to be of type B. (see previous example).

If you don't declare method to be virtual, you cannot override it, but you can hide it.

Can i override non virtual function in c++

You do not override say in B

from C++ override specifier :

In a member function declaration or definition, override ensures that the function is virtual and is overriding a virtual function from a base class. The program is ill-formed (a compile-time error is generated) if this is not true.

Look at that example :

#include <iostream>

class A
{
public:
void say()
{
std::cout << "From A\n";
}
};

class B : public A {
public:
void say()
//override
{
std::cout << "From B\n";
}
};

int main()
{
A a;
B b;

a.say();
b.say();
((A &) b).say();
}

Compilation and execution :

pi@raspberrypi:/tmp $ g++ c.cc
pi@raspberrypi:/tmp $ ./a.out
From A
From B
From A
pi@raspberrypi:/tmp $

Putting say virtual in A (so implicitely in B) ((A &) b).say(); prints From B because that time there is overriding

Is it possible to override a non-virtual method?

No, you cannot override a non-virtual method. The closest thing you can do is hide the method by creating a new method with the same name but this is not advisable as it breaks good design principles.

But even hiding a method won't give you execution time polymorphic dispatch of method calls like a true virtual method call would. Consider this example:

using System;

class Example
{
static void Main()
{
Foo f = new Foo();
f.M();

Foo b = new Bar();
b.M();
}
}

class Foo
{
public void M()
{
Console.WriteLine("Foo.M");
}
}

class Bar : Foo
{
public new void M()
{
Console.WriteLine("Bar.M");
}
}

In this example both calls to the M method print Foo.M. As you can see this approach does allow you to have a new implementation for a method as long as the reference to that object is of the correct derived type but hiding a base method does break polymorphism.

I would recommend that you do not hide base methods in this manner.

I tend to side with those who favor C#'s default behavior that methods are non-virtual by default (as opposed to Java). I would go even further and say that classes should also be sealed by default. Inheritance is hard to design for properly and the fact that there is a method that is not marked to be virtual indicates that the author of that method never intended for the method to be overridden.

Edit: "execution time polymorphic dispatch":

What I mean by this is the default behavior that happens at execution time when you call virtual methods. Let's say for example that in my previous code example, rather than defining a non-virtual method, I did in fact define a virtual method and a true overridden method as well.

If I were to call b.Foo in that case, the CLR would correctly determine the type of object that the b reference points to as Bar and would dispatch the call to M appropriately.

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

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

Overriding non-virtual function from abstract grandparent class

You cannot override a non-virtual function. It is as simple as that.

Methods in child classes can hide methods of parent classes when they have the same name, for example:

struct A {
void foo(){}
};
struct B : A {
void foo() {}
};

But thats not overriding. To override the method must be virtual. Thats one of the conditions that the override specifier helps to check:

struct A {
virtual void foo(){}
};
struct B : A {
void foo() override {} // <- error if A::foo is not virtual
};

PS: I have seen poor tutorials, that use the first example and call that overriding. Thats just wrong.

Preventing the use of an overridden non-virtual function - The correct way?

In response to OP's second edit:

Aliases are not like macros.

If you write using PtrType = T*, then const PtrType is actually
equivalent to T* const, which is a const pointer to a T object, not a pointer to a const T object. When aliases are used, further cv-qualifiers are always added on the top level. It is intuitive - if PtrType is a pointer to T, then const PtrType should be a const pointer to T.


As per the question, if you don't want users to call a virtual function, make it protected, so derived classes can implement it, but outside users cannot call it.


It is likely that you made the return type of bstnodeiterator::get_pointer() T* (instead of const T*).

You may be experiencing the pitfall of c++ covariant return types.

  • Both types are pointers or references (lvalue or rvalue) to classes. Multi-level pointers or references are not allowed.

  • The referenced/pointed-to class in the return type of Base::f() must be a unambiguous and accessible direct or indirect base class of (or is the same as) the
    referenced/pointed-to class of the return type of Derived::f().

  • The return type of Derived::f() must be equally or less cv-qualified than the return type of Base::f().

Note: c++ reference does not have the "(or is the same as)" clause, but it is added to be coherent with the standard"

So std::string* is a valid return type if the function is overriding a function with return type const std::string*.

Consider this example:

#include <string>

std::string s = "Hello, world";

struct Base {
virtual const std::string* foo() = 0;
};

struct Derived : Base {
std::string* foo() override {
return &s;
}
};

int main() {
Derived d;
d.foo()->assign("You can do this.");
return 0;
}

The above code compiles: you can modify the string pointed by d.foo() because it returns a std::string*.

Override non-virtual string property

This is how shadowing or hiding works i.e. (using new keyword with members of class), if you are expecting that holding derived class (CartFake) reference as base class (Cart) would give you access to the value of property of derived class (CartFake), you are wrong.

That would have happened if you had the property defined virtual in base class (Cart) and you had overriden it using override keyword in derived class (CartFake), but that is not the case.

For the behavior that you are expecting for that your code needs to be like:

public class Cart {
public virtual string Currency { get; set; } // I'm trying to override this
}

// My fake class
public class CartFake : Cart
{
public override string Currency { // This should hide SomeBaseBase.Cart.Currency - but it does not
get { return "USD"; }
set { value = "USD"; }
}
}

now when you access the property Currency using variable of type base class but object is actually of type Derived class, you will get USD back.

When you are accessing the Currency property using reference of type Cart it is hiding the property Currency defined in the CartFake.

You need to cast it back to CartFake, if you want to get USD as result of Currency like:

// class under test
public class SomeClassFake : Base {
public override Cart cart => new CartFake();

// Then when test is running I have this
var cartFake = cart as CartFake;
var currency = cartFake.Currency // will return USD
}

Refer to the question Difference between Shadowing and Overriding for more clarity.



Related Topics



Leave a reply



Submit