override keyword allows to make sure that the function will get overridden.
I am looking for the reverse functionality. So that - when I write a new function - I want to mark it with something to make sure it will not get accidentally overwritten.
(Also, I do not want to make it static, since it looks like to belong to an object rather than class)
I want to mark it with something to make sure it will not get accidentally overwritten.
You can use the final specifier. Example from cppreference:
struct Base
{
virtual void foo();
};
struct A : Base
{
void foo() final; // A::foo is overridden and it is the final override
void bar() final; // Error: non-virtual function cannot be overridden or be final
};
If you don't want a virtual function to be overridden in the derived class, you can use final:
Specifies that a virtual function cannot be overridden in a derived class or that a class cannot be inherited from.
e.g.
struct Base
{
virtual void foo() final; // foo cannot be overridden in the derived class
};
struct Derived : Base
{
void foo(); // Error: foo cannot be overridden as it's final in Base
};
final is the keyword you are looking for.
Remark: Be aware that override does not "make sure that the function will get overriden" as you put it. override in your derived class does make sure that you actually override a method of a base class, and not just introduce a new method that is similar to a virtual method of the base class.
To make sure that a method is overriden it would have to be pure virtual in your base class.
Also, static works exactly the other way round: static methods belong to the class, non-static methods need an object to be called.
Related
I have a class A and a class B that inherits from A. A has a foo method which I would like to override in B.
class A {
public:
void foo();
...
}
class B: public A {
public:
void foo();
...
}
The solution to this would of course be to define A::foo() as a virtual method, by declaring it as virtual void foo();. But the problem is that I can't do that, since the A class is defined in a third-party library so I would rather not change its code.
After some searching, I found the override keyword (so that the declaration for B::foo would be void foo() override;), but that didn't help me since that's not what override is for, override can apparently only be used on virtual methods to be sure that the method is really overriding another method and that the programmer didn't make a mistake, and it generates an error if the method isn't virtual.
My question is how can I achieve the same effect as making A::foo virtual without changing any of the code for A, but only the code for B?
A bit late. But you can use std::variant and delegate methods to the two classes A and B according to the concrete type.
If your compiler is not that up to date, use a tagged union instead.
As it is explained in The C++ programming language:
virtual void push(char c) = 0;
virtual void pop() = 0;
The word virtual means 'may be redefined later in a class derived from this one'
The =0 syntax says that some class derived from Stack must define the function.
So why =0 symbol is needed? Does it means that a derived class must define this function, and that's to say when there is no =0, some derived classes are not forced to define this method?
I'm confusing about this, need some help.
Your thoughts were right.
So why =0 symbol is needed? Does it means that a child class must
define this function, and that's to say when there is no =0, some
child classes are not forced to define this method?
Basically you can:
Make a method non-virtual
This doesn't allow any class deriving from the class that implements the method (through either public or protected) to change the method's behavior.
Make a method virtual
This allows (but doesn't enforce) any class deriving from the class that implements the method (through either public or protected) to change the behavior of the method in the base class. You don't even have to call the original base class method anymore so you can make severe changes if needed.
Make a method pure virtual ( virtual = 0 )
This enforces that any class deriving from the class that implements the method (through either public or protected) to implement some kind of behavior/body for this method. If the deriving class does not provide an implementation then this class will instantly become abstract itself. This allows to omit the behavior/body of the method in the base class and because of this it is not allowed to directly instantiate a class that has one or more pure virtual methods (abstract class).
So why =0 symbol is needed?
Consider the following:
struct foo
{
virtual void some() const { cout << "foo" << endl; }
};
struct bar : public foo
{
virtual void some() const { cout << "bar << endl; }
};
struct baz : public foo
{
}
Suppose you have a pointer foo *p pointing to some object, and you call p->some().
If p points to a bar object, it will print "bar".
If p points to a baz object, it will print "foo".
In some cases, this might not be what you want. You might want to specify that any derived class needs to override it. The =0 does that.
The purpose of an abstract class (those classes have pure virtual method, =0) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface.
Thus, if a subclass of an abstract class needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the abstract class.
That is the base concept for interface.
In short, it a way to be sure a derivative class will implement those methods from the base class.
So why =0 symbol is needed?
Virtual function with sequence = 0 is known as pure virtual function, (the sequence = 0 is known as pure-specifier), it makes the class an abstract class, which can't be instantiated. For the derived classes, if they want to make it possible to be instantiated, they have to implement the pure virtual function.
No objects of an abstract class can be created. Abstract types cannot be used as parameter types, as function return types, or as the type of an explicit conversion. Pointers and references to an abstract class can be declared.
For example,
class Stack {
virtual void push(char c) = 0;
};
...
Stack s; // Fail, Stack is an abstract class
and if
class Stack {
virtual void push(char c);
};
...
Stack s; // Fine, if you won't call `push()` on it.
First consider what is the reason to use virtual methods.
1.Interface(polymorphism).
Interface in C++ is a pure virtual class, which means, that all of its methods are pure virtual (like these two you've mentioned above), it has an virtual destructor and has no constructor (it's obvious, because we can't create its instances). It also shouldn't have any data.
Let's define an interface (pure abstract class in C++):
class Interface
{
public:
virtual ~Interface(){}
virtual void somePublicMethod() = 0;
};
And define the class, which is an implementation of interface:
class Implementation : public Interface
{
public:
~Implementation() override {}
void somePublicMethod() override {}
};
If you define another pure virtual method in interface:
virtual void anotherPublicMethod() = 0;
And you don't override it in implementation you will receive compilation error, when you will declare object of Implementation type, because real Implementation object must have definitions (bodies) for all derived methods.
Yo can also define default behavior of some interface's method:
void Interface::somePublicMethod()
{
//define default behavior here
}
And call it in derived class:
void Implementation::somePublicMethod()
{
Interface::somePublicMethod();
}
How interface is used in polymorphism you will read in other topics.
2."Ordinary" Inheritance.
In "ordinary" inheritance you should use virtual methods instead of pure virtual ones, because you want to have instances of both Base class and Derived class(es). Virtual methods only indicates, that they could be overridden in derived class(es).
Conclusion
In general, if you want to have an instance of any class, this class must have all methods defined (so the must have bodies and it's obvious that they mustn't be pure virtual).
The code segment below works fine:
#include <iostream>
#include <string>
using namespace std;
class HelpInterface {
public:
void getHelp();
};
class Applicaiton : public HelpInterface {
public:
void getHelp() {
cout << "General help";
}
};
int main(void) {
Applicaiton applicaiton;
applicaiton.getHelp();
}
Make the getHelp function virtual in HelpInterface class and I will get a linker error:
class HelpInterface {
public:
virtual void getHelp();
};
If I make an empty implemenation of getHelp as below things will work again:
class HelpInterface {
public:
virtual void getHelp() {};
};
Can someone please help me understand why virtual throws a linker error unless I have an implementation for getHelp in the base class and why a non-virtual function with no implementation works just fine? In this example, the base function never gets called.
Here is a screenshot of VS2013 with the linker error:
If you want your base class method to be virtual and provide no implementation, you must set it equal to zero like this:
class HelpInterface {
public:
virtual void getHelp() = 0;
};
This is known as a pure virtual method. It has the effect of making your class abstract and forcing all of its derived classes to provide an implementation of the method. Consequently, take note that you will no longer be able to create an instance of the base class because it is abstract.
When a method is in the base class but isn't virtual the linker will not actually reference the implementation of the method if you don't have an explicit call to that method on either a pointer/reference to the base type (On an instance of the derived class) or an instance of the base type.
Virtual functions can be implemented a number of different ways, and are implementation specific. One of the most common is by using a virtual table. (Also known by virtual method table, virtual function table, virtual call table, dispatch table, vtable, or vftable), and I'm pretty sure your compiler (VS2013) uses this method of implementing virtual functions.
A virtual table is a table of function pointers for the virtual member functions. The class instance would contain a pointer to the table that the class belongs to.
When you make a function virtual the linker tries to put it into the virtual table for that type. It doesn't matter whether you call it or not or instantiate a base class (also an implementation specific detail).
As qexyn has already answered, to get around that you declare the method as pure virtual by adding = 0 after the virtual function declaration. This tells the linker to put a null pointer in the virtual function table for the class. You can also declare the virtual function pure virtual and also provide an implementation. This forces the derived classes to implement that function, but allows them to choose to use the default method.
The reason for this is that your base class definition is using indirection to get the actual function for Application.
This is often implemented with a function pointer, but in any case there could be a derived class that doesn't override the base class implementation.
Although this isn't usually reproducible that is simply because member functions are implicitly declared inline and when the implementation is visible an optimizing compiler will do exactly that; inline the function. The proof is in the optimization.
What you want, is to make sure that every derived class from your base implements getHelp(). This is a common idiom and is a core language feature. You want a "pure virtual function". This will make your base class an "abstract base class" which is actually a synonym for "interface" in object-oriented jibber-jabber.
The way to do this in C++ is with a special member-function specific syntax after all of the member function qualifiers (I'm using trailing return types here cause I think they're pretty):
class base{
public:
virtual auto func() -> void = 0;
};
This specifies that base is an abstract base class with a pure virtual function func() that all classes derived from it will implement.
In your case you would write:
class HelperInterface{
public:
virtual void getHelp() = 0; // probably want const qualifier
};
And just leave Application as it is.
You learn something every day, huh?
Here is a very basic example:
class Base {
public:
virtual void sayHi() const {}
virtual void sayHello() {}
virtual ~Base(){}
};
class Derived : public Base {
public:
virtual void sayHi() {}
virtual void sayHello() const {}
};
int main()
{
Base *b = new Base();
Base *d = new Derived();
return 0;
}
The Base's vptr, in 'b' has virtual functions of Base class. The derived class object 'd' however, on inspection, list virtual functions of only base.
The question here is not, why are the functions not being overridden so the use of override keyword isn't required here. The question is, why doesn't a particular class's VTable contain its own virtual functions? In this case why vtable of 'd' doesnt contain D::sayHi and D::sayHello?
I am open to downvotes, but be brave to mention and tell the reason.
edit:
I know that the CONSTness might look wrong here, but the question is not about overriding.
This is specifically tried out in VS2012 Update4
Here you have different function overloads that do not override the defined virtual functions:
virtual void sayHi() const {}
virtual void sayHello() {}
void sayHi() {} // non virtual function with a different signature (no const)
void sayHello() const {} // non virtual function with a different signatuere (const)
If you want to avoid such subtle errors, use the keyword override : if the function that you think overrides a virtual function of the base class has a different signature or doesn't even exist (e.g.typo...) the compiler will generate an error.
Edit following your edit:
I see that you've updated the code to make the overloaded non overriding functions virtual as well.
Now the vtable of the derived function contains four distinct functions. However, through the base pointer you can only access the virtual functions defined in the base. This is why the MSVC debugger shows you only 2:
By the way, the debugger seems to always show the vtable as a member of the Base. But if you look at the assembler generated, you'll see the mangled names of all the virtual functions of the derived class in its vtable:
Your Hi function does not override the base class Hi function as their const specifiers are wrong.
The same is true for your Hello functions, albeit the other way round.
If you use C++11 or later you can use the override keyword to make sure this doesn't happen.
It was already mentioned that you are not overriding the functions as you are changing the functions signature by adding a const.
Concerning your actual questions:
It will use the vtable-pointer from the base class to point to its own vtable that has different entries. Thats just how it works. It "looks" like the base class but behaves "different". Thats polymorphic behaviour in C++.
If each deriving class would add its own vtable, a lot of things would be broken in C++. Multiple vtable pointers will only be part of an instance of a class, which derives from multiple classes containing virtual functions or when using virtual inheritance.
If I have the following override of a virtual event:
void derivedClass::method(event)
{
// my stuff
baseClass::method(event); // <--
}
what does the // <--- line does? What does it call? I don't think it calls the base class' method because it's virtual (so no body)
As you are suggesting, it calls the base class' method. The fact that it is virtual it only means it can be overridden and still access to the derived class' method from a pointer/reference to the base class.
The reason to do that can be easily seen with an example:
class Base {
public:
virtual void foo() {
/* do some generic stuff */
}
};
class Derived : public Base {
public:
void foo() {
/* do some specific stuff */
/* if you also want to do the generic stuff,
you can call the same method from the base class. */
Base::foo();
}
}
It might be the case that you do not want to do the generic stuff for Derived class. Then you would just remove the call to Base::foo().
Here you have a good reference on virtual methods.
It does call the base class method. Yes, the derived method is being called "polymorphically", but it can call its base method using Base::method
When qualified name (<class name>::<method name>) is used in a class method call, the method is called directly, non-virtually. In your example, baseClass::method is called. Since qualified name is used, the fact that the method is virtual means absolutely nothing and makes no difference whatsoever.