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?
Related
This may seem like a simple question, but I can't find the answer anywhere else.
Suppose I have the following:
class Abstract {
public:
virtual void foo() = 0;
virtual void bar();
}
class Derived : Abstract {
public:
virtual void foo();
}
Is it ok that class Derived does not implement the bar() function?
What if not ALL of my derived classes need the bar() function, but some do.
Do all of the virtual functions of an abstract base class need to be implemented in the derived classes, or just the ones that are pure virtual?
Thanks
Derived classes do not have to implement all virtual functions themselves. They only need to implement the pure ones.1 That means the Derived class in the question is correct. It inherits the bar implementation from its ancestor class, Abstract. (This assumes that Abstract::bar is implemented somewhere. The code in the question declares the method, but doesn't define it. You can define it inline as Trenki's answer shows, or you can define it separately.)
1 And even then, only if the derived class is going to be instantiated. If a derived class is not instantiated directly, but only exists as a base class of more derived classes, then it's those classes that are responsible for having all their pure virtual methods implemented. The "middle" class in the hierarchy is allowed to leave some pure virtual methods unimplemented, just like the base class. If the "middle" class does implement a pure virtual method, then its descendants will inherit that implementation, so they don't have to re-implement it themselves.
Only the pure virtual methods have to be implemented in derived classes, but you still need a definition (and not just a declaration) of the other virtual methods. If you don't supply one, the linker might very well complain.
So, just putting {} after your optional virtual method gives you an empty default implementation:
class Abstract {
public:
virtual void foo() = 0; // pure virtual must be overridden
virtual void bar() {} // virtual with empty default implementation
};
class Derived : Abstract {
public:
virtual void foo();
};
A more involved default implementation would go into a separate source file though.
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined.
Simply put the rule is:
If your derived class overiddes the Base class virtual method then it should provide a definition as well, If not then the Base class should provide the definition of that method.
As per the above rule in your code example, virtual void bar(); needs a definition in the Base class.
Reference:
C++03 Standard: 10.3 Virtual functions [class.virtual]
A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).
So either you should make the function pure virtual or provide a definition for it.
The gcc faq doccuments it as well:
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.
Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.
The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.
Yes, that's fine ... you only need to implement any pure virtual functions in order to instantiate a class derived from an abstract base class.
Yes, Its correct that a Derived class has to OVERRIDE the function which is Pure Virtual in the Parent Class. Parent class having a Pure Virtual Function is called Abstract Class only because it's Child class must give their own body of the Pure Virtual Function.
For the Normal Virtual Functions:-
Its not necessary to override them further, as some child class may have that function, some may not have.
Main purpose of Virtual Function mechanism is Run Time Polymorphism, whether main purpose of Pure Virtual Function(Abstract Class) is to make it mandatory to have the same name Function with own's body.
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).
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.
Is it essential to have a definition for a virtual function?
Consider this sample program below:
#include <iostream>
using namespace std;
class base
{
public:
void virtual virtualfunc();
};
class derived : public base
{
public:
void virtualfunc()
{
cout << "vf in derived class\n";
}
};
int main()
{
derived d;
return 0;
}
This gives the link-error:
In function base::base():: undefined reference to vtable for base
I do not have the definition for the virtual function in base class. Why is this error occurring even though I have not explicitly invoked the virtual function?
The interesting thing which I find is that if I do not instantiate an object of class derived, the link error is no longer there. Why is this? What has instantiation got to do with the above link error?
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined.
Reference:
C++03 Standard: 10.3 Virtual functions [class.virtual]
A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).
So either you should make the function pure virtual or provide a definition for it.
If you are using gcc, You might get some weird errors if you fail to follow this standard specification. The gcc faq doccuments it as well:
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.
Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.
The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.
You need to provide an implementation of a virtual function ( with its default behaviour ) unless you define the function to be "pure virtual".
So your example could be:
class base
{
public:
void virtual virtualfunc() {} //intentionally do nothing;
};
or
class base
{
public:
void virtual virtualfunc()=0; //pure virtual;
};
You either need to provide a definition, or mark it as abstract/pure-vitual.
void virtual virtualfunc() = 0;
In response to the error about the vtable: the virtual command in this case tells c++ to produce a virtual table of the methods in the base class. In this way when you use polymorphism, C++ is able to replace the base class virtual methods with the methods from the derived class with the same name during run time. This error is telling the user that this replacement is not possible. To fix this error, you will either need to implement the method or set it as pure virtual by adding "=0" at the end of the definition.
In response to the edits: The reason you are not getting an error when you instantiate the object as a base class is because the base class does not need to access the virtual table. On the other hand if you actually try to use this method, you should get an error since no implementation exists. In other words even though you can instantiate an object of the base class its not a complete class.
Yes you would need a body, but perhaps what you are referring to is called a pure virtual functions, which would not need a definition in the base class.
The syntax to define those is as follows:
void virtual virtualfunc() = 0;
With the struct definition given below...
struct A {
virtual void hello() = 0;
};
Approach #1:
struct B : public A {
virtual void hello() { ... }
};
Approach #2:
struct B : public A {
void hello() { ... }
};
Is there any difference between these two ways to override the hello function?
They are exactly the same. There is no difference between them other than that the first approach requires more typing and is potentially clearer.
The 'virtualness' of a function is propagated implicitly, however at least one compiler I use will generate a warning if the virtual keyword is not used explicitly, so you may want to use it if only to keep the compiler quiet.
From a purely stylistic point-of-view, including the virtual keyword clearly 'advertises' the fact to the user that the function is virtual. This will be important to anyone further sub-classing B without having to check A's definition. For deep class hierarchies, this becomes especially important.
The virtual keyword is not necessary in the derived class. Here's the supporting documentation, from the C++ Draft Standard (N3337) (emphasis mine):
10.3 Virtual functions
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 (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
No, the virtual keyword on derived classes' virtual function overrides is not required. But it is worth mentioning a related pitfall: a failure to override a virtual function.
The failure to override occurs if you intend to override a virtual function in a derived class, but make an error in the signature so that it declares a new and different virtual function. This function may be an overload of the base class function, or it might differ in name. Whether or not you use the virtual keyword in the derived class function declaration, the compiler would not be able to tell that you intended to override a function from a base class.
This pitfall is, however, thankfully addressed by the C++11 explicit override language feature, which allows the source code to clearly specify that a member function is intended to override a base class function:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(int) override; // ill-formed - doesn't override a base class method
};
The compiler will issue a compile-time error and the programming error will be immediately obvious (perhaps the function in Derived should have taken a float as the argument).
Refer to WP:C++11.
Adding the "virtual" keyword is good practice as it improves readability , but it is not necessary. Functions declared virtual in the base class, and having the same signature in the derived classes are considered "virtual" by default.
There is no difference for the compiler, when you write the virtual in the derived class or omit it.
But you need to look at the base class to get this information. Therfore I would recommend to add the virtual keyword also in the derived class, if you want to show to the human that this function is virtual.
The virtual keyword should be added to functions of a base class to make them overridable. In your example, struct A is the base class. virtual means nothing for using those functions in a derived class. However, it you want your derived class to also be a base class itself, and you want that function to be overridable, then you would have to put the virtual there.
struct B : public A {
virtual void hello() { ... }
};
struct C : public B {
void hello() { ... }
};
Here C inherits from B, so B is not the base class (it is also a derived class), and C is the derived class.
The inheritance diagram looks like this:
A
^
|
B
^
|
C
So you should put the virtual in front of functions inside of potential base classes which may have children. virtual allows your children to override your functions. There is nothing wrong with putting the virtual in front of functions inside of the derived classes, but it is not required. It is recommended though, because if someone would want to inherit from your derived class, they would not be pleased that the method overriding doesn't work as expected.
So put virtual in front of functions in all classes involved in inheritance, unless you know for sure that the class will not have any children who would need to override the functions of the base class. It is good practice.
There's a considerable difference when you have templates and start taking base class(es) as template parameter(s):
struct None {};
template<typename... Interfaces>
struct B : public Interfaces
{
void hello() { ... }
};
struct A {
virtual void hello() = 0;
};
template<typename... Interfaces>
void t_hello(const B<Interfaces...>& b) // different code generated for each set of interfaces (a vtable-based clever compiler might reduce this to 2); both t_hello and b.hello() might be inlined properly
{
b.hello(); // indirect, non-virtual call
}
void hello(const A& a)
{
a.hello(); // Indirect virtual call, inlining is impossible in general
}
int main()
{
B<None> b; // Ok, no vtable generated, empty base class optimization works, sizeof(b) == 1 usually
B<None>* pb = &b;
B<None>& rb = b;
b.hello(); // direct call
pb->hello(); // pb-relative non-virtual call (1 redirection)
rb->hello(); // non-virtual call (1 redirection unless optimized out)
t_hello(b); // works as expected, one redirection
// hello(b); // compile-time error
B<A> ba; // Ok, vtable generated, sizeof(b) >= sizeof(void*)
B<None>* pba = &ba;
B<None>& rba = ba;
ba.hello(); // still can be a direct call, exact type of ba is deducible
pba->hello(); // pba-relative virtual call (usually 3 redirections)
rba->hello(); // rba-relative virtual call (usually 3 redirections unless optimized out to 2)
//t_hello(b); // compile-time error (unless you add support for const A& in t_hello as well)
hello(ba);
}
The fun part of it is that you can now define interface and non-interface functions later to defining classes. That is useful for interworking interfaces between libraries (don't rely on this as a standard design process of a single library). It costs you nothing to allow this for all of your classes - you might even typedef B to something if you'd like.
Note that, if you do this, you might want to declare copy / move constructors as templates, too: allowing to construct from different interfaces allows you to 'cast' between different B<> types.
It's questionable whether you should add support for const A& in t_hello(). The usual reason for this rewrite is to move away from inheritance-based specialization to template-based one, mostly for performance reasons. If you continue to support the old interface, you can hardly detect (or deter from) old usage.
I will certainly include the Virtual keyword for the child class, because
i. Readability.
ii. This child class my be derived further down, you don't want the constructor of the further derived class to call this virtual function.