View Full Version : C++ and pure virtual functions
Fenix Down
01-08-2004, 09:57 PM
I'm curious if anyone knows why the compiler behaves the way it does in this situation: I have a pure virtual function in a base class, which is called by another function in that class (not pure virtual, though this isn't important). Now, this compiles fine on its own. BUT, when I derive from the base class, and implement the virtual function in the derived class (which is a concrete class, not abstract), the compiler throws an "unresolved external symbol" error, as if the function is not implemented.
However, when I add a body to the pure virtual function in the base class, the compiler is satisfied. My question is why the hell does the compiler throw a fit when the base class is automatically abstract (since it has a pure virtual function), and cannot be instantiated . In other words, it's true that the pure virtual function is technically undefined if it has no body, but it can't be called unless it is defined by a derived class. A derived class containing this function can't be instantiated otherwise, no matter how many levels of derivation you have since a pure virtual function automatically makes the class abstract. I also don't quite get why it compiles fine until you derive from the base class.
Someone should be able to answer this. I've been programming with C++ for only about 4.5 years, still have a long way to go.
Lizardsoft
01-08-2004, 10:23 PM
A simplified example of your code would be helpful, along with what compiler you are using.
Is the call to the pure virtual method taking place sometime during construction or destruction (maybe not in the constructor or destructors themselves, but off of methods they might call)? If so, the problem you're seeing is not unexpected. You can only reliably call a pure virtual method when an object is fully constructed.
Suppose you have base class A and B derives from it. Well when you create a B, A's constructor is called first and B doesn't exist yet, so any attempt to call virtual functions of B will cause problems. Similar problems will occur if you try during the destructor phase.
If you're not calling the method from the base class's constructor or destructor or a method that one of those calls either directly or through nested calling, then I'd need a bit more information (small sample like Lizardsoft suggested) to be sure exactly what is happening.
gfm, your suggestion seems correct, also there's the problem that people tend to forget
that the base class's destructor needs to be declared 'virtual' in order to be called automatically
(a very common mistake that will lead to memory leaks when you deallocate stuff in your base destructor)
however the original poster seems to have problems at compile time. what doesn't make sense to me
is that Fenix says:
"However, when I add a body to the pure virtual function in the base class, the compiler is satisfied."
Of course it is satisfied!? adding a body just makes the base class a normal class with a
virtual method (which can furthermore be overloaded by a derived class), so it is perfectly valid to
declare an instance of that base class. (or am i missing something?)
look at this snippet, it should be fine:
--------------------------------
class Base
{
protected:
virtual void foo() = 0; //ensure (at compile time) that derived classes will implement this method.
private:
void bar()
{
//call implementation of foo().
//compiles fine (it'll be looked up at runtime).
foo();
}
};
class Derived : public Base
{
//implement the foo() interface.
//(the 'virtual' is optional IIRC)
/*virtual*/ void foo()
{
int i = 0;
// ...
}
};
--------------------------------
i hope everything i said is correct.
Haze
ergas
01-09-2004, 02:20 AM
The object orientation standards of c++ is interesting. Check the attachment, compile and observe the phenomenon :) Write the same code with Java, then everyting will work fine.
The phenomenon you will observe needs some long discussion so I just post the code, then we could discuss iteratively then after.
:)
ergas
01-09-2004, 02:24 AM
Additionally, as far as I know, c++ oop standards don't let you call sub-class's (derived classes) methods from base constructor.
Again, as far as I know, this is the same with Java oop standards.
ergas
01-09-2004, 02:30 AM
I checked calling sub-class's method from base constructor with Java. It works! I adore Java from then on :D
ggambett
01-09-2004, 05:23 AM
What symbol can't the compiler found? Base::foo() or Derived::foo()?
I had my share of weird linker errors with virtual functions... in one case, I had to switch the order of the libraries passed in the command line to fix it!
I agree with Lizardsoft, post some code.
Landon_Fox
01-09-2004, 06:36 AM
I witnessed a similar effect in my coding as well. What I did was just put in one line to call my error recording function with something along the lines of "I should have been called." So far I haven't had that error reported.
Fenix Down
01-09-2004, 01:07 PM
Originally posted by haze
however the original poster seems to have problems at compile time. what doesn't make sense to me
is that Fenix says:
"However, when I add a body to the pure virtual function in the base class, the compiler is satisfied."
Of course it is satisfied!? adding a body just makes the base class a normal class with a
virtual method (which can furthermore be overloaded by a derived class), so it is perfectly valid to
declare an instance of that base class. (or am i missing something?)
Actually, believe it or not you CAN have a pure virtual function with a body. Yes, weird as it is, it's possible. Oh the wonders of the C++ OOP framework. :)
I looked at the code again, and realized that the pure virtual function is being called not only from a member function, but also from the destructor. That explains it then, thanks gfm. :) I'm glad someone was able to understand my rambling without a code sample. :)
I have a followup question then. Is it possible to call an overridden virtual function from a base class destructor (such that the overridden version is used)? I just realized that the compiler probably wants a body for the function because it plans on calling the base class version from the destructor.
For instance, what I'm doing is I have a virtual Release_Resource() function (which I wanted to make pure virtual with no body but that's not allowed since it's called in the destructor). That function is overridden in the derived class so that it can perform custom resource deallocation. Does this mean that when it's called in the base class destructor the compiler will just use the base class version and not the derived class even though it's virtual and overridden? (since the derived class is technically dead already?) That's quite a bummer then. :( Not the end of the world, but doesn't let me make the code as sleek as I'd like. :) I wanted to use polymorphism to do some cool stuff (like this).
If that's not very clear I can post a code sample. But it's basically "what happens when you call a virtual function (that has an overridden version in an inherited class) from the base class destructor."
You're going to have to live with unsleek code, I'm afraid.
If you call a virtual from a constructor or destructor, it will always call the corresponding method of the base call and not any that inherit from it. C++ does this to save you from the situation where you're attempting to call into the virtual function dispatch table of an unconstructed object. At least that is what the standard says. Depending upon your compiler you may actually get away with doing this, but relying on a compiler bug for your code to work correctly is, of course, a very bad idea.
I agree that it would be nice if you could do what you're trying to do.
Fenix Down
01-09-2004, 05:18 PM
Oh well, I'll just have to use a manual way then. Thanks a lot for your help! :cool: