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.
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*
.
C++ override specifier without virtual? Does override imply virtual?
The answer you're looking for is in https://en.cppreference.com/w/cpp/language/virtual
If some member function vf is declared as virtual in a class Base, and some class Derived, which is derived, directly or indirectly, from Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).
Is it a good idea to always mark non-virtual methods with final?
A program that contains a non-virtual function, and which has every non-virtual function as final
and follows the C++ standard, is guaranteed to be completely bug free.
So there is that.
Still: I advise against it.
It also does not exist. The final
positional keyword can only be applied to virtual
functions. The first paragraph is known as a vacuous satisfaction joke: every example of a non-existing thing has every property, because there are no examples.
Creating a non-overriding virtual final
function would be confusing to people reading it. It would prevent a descendent type from declaring a method with identical signature: but it would not prevent a slightly different signature, so it is mostly pointless.
Related Topics
Statically Declared 2-D Array C++ as Data Member of a Class
How to Programmatically Cause a Core Dump in C/C++
Cin.Ignore(Numeric_Limits<Streamsize>::Max(), '\N')
Why Is There No Transform_If in the C++ Standard Library
How to Completely Disable Calls to Assert()
C++ Threads, Std::System_Error - Operation Not Permitted
Overloaded Functions Are Hidden in Derived Class
Is the Size of a Struct Required to Be an Exact Multiple of the Alignment of That Struct
C++ Template Copy Constructor on Template Class
How to Find Where an Exception Was Thrown in C++
Should I Pass an Std::Function by Const-Reference
Passing Integers as Constant References Versus Copying
C++ Filehandling: Difference Between iOS::App and iOS::Ate
Error: Variable "Cannot Be Implicitly Captured Because No Default Capture Mode Has Been Specified"