Linking fails when missing implementation of a not-used pure virtual method - c++

I have a class, which inherits from a class with a pure virtual functions.
Now I need to add another class, which doesn't need some method. I got an idea not to implement this method, instead of always throwing an exception when this method is called, like in the next example :
#include <iostream>
class ibase {
public:
virtual void foo() = 0;
virtual void boo() = 0;
};
class base1 : public ibase {
public:
virtual void foo(){ std::cout<<"base1::foo"<<std::endl; }
virtual void boo(){ std::cout<<"base1::boo"<<std::endl; }
};
class base2 : public ibase {
public:
virtual void foo() { std::cout<<"base2::foo"<<std::endl; }
virtual void boo();
};
int main()
{
ibase *inst1 = new base1;
ibase *inst2 = new base2;
inst1->foo();
inst1->boo();
inst2->foo();
}
But when I tried to compile using next compiler options :
g++ dfg.cpp -ansi -pedantic -Wall
this example produced next output (using g++ 4.3.0) :
/tmp/ccv6VUzm.o: In function `base2::base2()':
dfg.cpp:(.text._ZN5base2C1Ev[base2::base2()]+0x16): undefined reference to `vtable for base2'
collect2: ld returned 1 exit status
Can someone explain why the linking fails? The method boo() is not called.

The vtable for base2 is created - you use a base2. The vtable references boo() - so you need to define it.
10.3/8:
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).

The One-Definition Rule states that each function that is used must be defined exactly once. The definition of the term used includes the following line:
a virtual function is used if it is
not pure
That means that all non-pure virtual functions have to be defined even if they aren't called

It fails because the internal vtable needs a place to point to. It doesn't matter if it is called, the vtable is still created.
Create an empty body for the method and you should be good to go.

You have to implement the method in base2, there is no way around it. Polymorphism is a run time behavior, and there is no way for the linker to know that boo will never be called. You can simply provide a dummy implementation in the base class instead of making it pure virtual if its not mandatory to implement the method in derived class.

boo may not be invoked in reality but it is used to construct the v-table for base2.
You have to define what behaviour will happen is someone has a base2 and calls boo() on it (via its base class pointer) even if there is no point in the code where this is actually invoked. It is part of the contract of implementing an ibase.
The design is of course flawed, and if you want a class that allows a foo only there should be an interface for that.
If your particular instance is that a call is a no-op then that IS a behaviour for the class.

You just forgot to implement virtual void base2::boo (). You have to implement it in order to instantiate base2 class. Otherwise you can leave it pure-virtual by not declaring it in base2 class.

Related

Virtual function and inheritance in C++

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?

Confused about non pure virtual classes in C++, what are they for?

I have a class declared as follow:
class TestFoo {
public:
TestFoo();
virtual void virtualFunction();
void nonVirtualFunction();
};
that I try to implement this way
TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
which on compilation returns the error:
undefined reference to vtable for TestFoo
I tried :
TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
void TestFoo::virtualFunction(){}
which compiles ok which is consistent to the answers to these posts:
Undefined reference to vtable
undefined reference to vtable
What confuses me is that I thought the whole point of declaring a virtual function is that I would not need to define it. In this example, I am not planning to create any instance of TestFoo, but to create instances of (concrete) classes inheriting from TestFoo. But still, I want to define the function nonVirtualFunction for every subclasses of TestFoo.
Something I did not get right ?
Thanks !
the whole point of declaring a virtual function is that I would not
need to define it
Not quite, it says "I may want to replace the implementation of this function by something else in a derived class."
I may have misunderstood your question, but you seem to imply that you don't think you can define pure virtual member function in C++, which you can. You can declare one as follows.
virtual void virtualFunction() = 0;
Normally, a pure virtual function won't be defined, but of course you can. That says "There is no default implementation of this function because it won't always make sense, but I'll provide you with an implementation that you can opt into."
By the way, if a class has any virtual functions, you should also define a virtual destructor, as it is perfectly legal (and often recommended) to have a base class (smart) pointer to a derived class - without a virtual destructor, the object may not be deleted correctly.
... I thought the whole point of declaring a
virtual function is that I would not need to define it ...
For that facility you have a feature called pure virtual methods:
virtual void virtualFunction() = 0; // no linking error now
Note that, a virtual method cannot remain unimplemented. The reason is that for every virtual method declared inside a class body there has to be a vtable entry. Failing to find its body results in linking error.
Purpose of this restriction:
Unless a class is abstract - that is it has at least one virtual function - there is no way you can guarantee to the compiler that you are not going to declare an object of TestFoo. What happens when you do following:
DerivedOfTestFoo obj1;
TestFoo obj2 = obj1, *p = &obj2; // object slicing
p->virtualFunction(); // where is the body?
Other situation; in constructor there is no virtual mechanism:
TestFoo::TestFoo () {
this->virtualFunction(); // where is the body?
}
We can conclude that, compilers follow the rule, "Better to be safe than sorry". :)
Your description matches perfectly with the case of an abstract class. Declare your virtual function as:
virtual void VirtualFunction () = 0;
This means that you are not implementing the function in this class. As a result, the class becomes abstract. That is, no bare objects of this class can be instantiated.
Also, you should provide a virtual destructor.
Update: Some clarifications...
The language allows you to redefine a non-virtual function. Though, the wrong version might be called in some cases:
derived D; // rB is a reference to base class but it
base & rB=D; // points to an object of the derived class
rB.NonVirtualFunction (); // The base-class version is called
For this reason, redefining a non-virtual function is strongly discouraged nowadays. See Scott Meyers' "Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs", item 36: "Never redefine an inherited non-virtual function."
See also item 7: "Declare destructors virtual in polymorphic base classes". An example:
base * pB = new derived;
delete pB; // If base's destructor is not virtual,
// ~derived() will not be called.
In case you wonder why isn't everything virtual by default, the reason is that calling a virtual function is slightly slower than calling a non-virtual one. Oh, and objects of classes with virtual functions occupy a few more bytes each.
If you want make this virtual function as pure virtual function,do not want to define it then, virtual void virtualFunction() = 0;

C++ "Virtual functions but no virtual destructors"

I have a base class Media and several derived classes, namely DVD, Book, etc...
The base class is written as:
class Media{
private:
int id;
string title;
int year;
public:
Media(){ id = year = 0; title = ""; }
Media(int _id, string _title, int _year): id(_id), title(_title), year(_year) {}
// virtual ~Media() = 0;
void changeID(int newID){ id = newID; }
virtual void print(ostream &out);
};
The thing is: without the destructor, GCC gives me a bunch of warnings class has virtual functions but non-virtual destructor, but still compiles and my program works fine. Now I want to get rid of those annoying warnings so I satisfy the compiler by adding a virtual destructor, the result is: it doesn't compile, with the error:
undefined reference to `Media::~Media()`
Making the destructor pure virtual doesn't solve the problem.
So what has gone wrong?
You need to also define the virtual destructor, not only add it.
//Media.h
class Media{
//....
virtual ~Media() = 0;
};
//Media.cpp
#include "Media.h"
//....
Media::~Media() {};
The reason you get the warnings is that all classes that will be derived from should have a virtual or protected (credit #Steve) destructor, otherwise deleting an instance via a pointer to a base class results in undefined behavior.
Note you HAVE TO provide a definition for destructors, even if they are pure virtual.
The thing is: without the destructor, GCC gives me a bunch of warnings "class has virtual functions but non-virtual destructor", but still compiles and my program works fine
This is an annoying warning in Modern C++, but in old object-style C++ it is generally correct.
The problem is about the way your objects are destructed. A simple test:
#include <iostream>
class Base {};
class Derived: public Base { public: ~Derived() { std::cout << "Aargh\n"; } };
int main() {
Base* b = new Derived();
Derived* d = new Derived();
delete d;
delete b;
}
This prints:
Aargh
Yep, only once.
The problem is that when you call delete on a variable of type Base*, the Base::~Base() method is called. If it is virtual, then the call is dynamically dispatched to the final method (based on the dynamic type), in this case Derived::~Derived(), but if it is not, then Derived::~Derived() is never called, thus never executed.
Therefore, if you wish to call delete (or use smart pointers which do it for you) on base types, then you need to add virtual ~Base() {} in their class definitions. This is why gcc warns you when you create a polymorphic class without a virtual destructor.
Note: time changed, and since then I implemented -Wdelete-non-virtual-dtor in Clang and it was replicated in gcc as well.
-Wnon-virtual-dtor is useful for library writers (as it warns on the base class), but may have a higher false positive rate; on the other hand -Wdelete-non-virtual-dtor fires at the call site, and has a much lower false positive rates (which you can generally work around by peppering final to remove the "polymorphic" property of the class).
What you have commented out is a pure-virtual declaration for a destructor. That means the function must be overridden in a derived class to be able to instantiate an object of that class.
What you want is just a definition of the destructor as a virtual function:
virtual ~Media() {}
In C++ 11 or newer, it's generally preferable to define this as defaulted instead of using an empty body:
virtual ~Media() = default;
You should implement the virtual destructor, not make it pure virtual.
Look at this similar question (identical maybe from the point of view of the virtual destructor error, not the warning) for more info.
EDIT: more generic solution, in reply to LuchianGrigore's comment (thank you for pointing it out)
You can also make the destructor pure virtual and implement as it is pointed in the above mentioned question.
The use of virtual destructors in you classes should be to prevent instantiation of the base class (i.e. when you have no other pure virtual methods to make the class abstract).
Uncomment declaration first and then
Try adding following line after class declaration
Media::~Media(){}

Should a virtual function essentially have a definition?

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;

Appended '= x' after a method declaration in c++

In C++, when a method is declared, I've noticed that sometime the method may have an assignement appended to it.
Could anyone tell me what this is?
For example:
virtual void MyMethod () = 0;
What doe the '= 0' mean. :)
Thanks everyone !!!
It means it's a pure virtual function, i.e. no actual definition of it is available in this class and it must be overridden in a subclass. It's not actually an assignment as such, zero is the only value you can "assign".
And this is C++ syntax; in C# the same would be accomplished with the abstract keyword.
In C++ this means that the method is a pure virtual method.
This means that an instance of this particular class-type cannot be instantiated. You can only create instances of classes derived from this, which override all pure virtual methods in the base class.
A base class with pure virtual methods defines an interface that derived classes have to implement, and is not meant to be used on its own.
Contrary to what calmh claims, as far as I know pure virtual functions can be implemented and they can be called explicitly.
#include <cstdio>
class A
{
public:
virtual void foo() const = 0; //pure virtual
};
void A::foo() const { puts("A::foo"); }
class B: public A
{
public:
virtual void foo() const { puts("B::foo"); }
};
int main()
{
//A a; //this would be an error - main point of having pure virtual functions
B b;
b.foo();
b.A::foo();
}
Usually one wouldn't do this, though, except perhaps if the virtual destructor is pure in a base class (in this case it has to be defined).
In C#, that is a syntax error.
If you meant C++, see calmh's answer.