[comp.lang.c++] vtbl for abstract class : WHY ?

tom@runxtsa.runx.oz.au (Thomas Antalffy) (08/30/90)

When I make a class abstract by assigning 0 to one of its virtual methods, 
my C++ compiler generates a virtual function table and puts the address of 

		char __pure_virtual_called() 

in the appropriate slot. This later creates a link error, because there is 
no default implementation of this function.

I assume that this mechanism is there to give you the chance of putting 
error handling in __pure_virtual_called().

What puzzles me is that my compiler (Glockenspiel 2.0c) gives an error 
message if a derived class of an abstract class does not redefine the method. 
I.e. the compiler guarantees that methods of abstract classes are implemented 
in all derived classes, so it will never have to call the abstract class's 
method. In fact, I do not see why it needs a virtual function table for an 
abstract class at all.

Does anyone know the answer to any of these questions ?

Regards,
Thomas.

ark@alice.UUCP (Andrew Koenig) (08/30/90)

In article <2206@runxtsa.runx.oz.au>, tom@runxtsa.runx.oz.au (Thomas Antalffy) writes:
> When I make a class abstract by assigning 0 to one of its virtual methods, 
> my C++ compiler generates a virtual function table and puts the address of 

> 		char __pure_virtual_called() 

> in the appropriate slot. This later creates a link error, because there is 
> no default implementation of this function.

> I assume that this mechanism is there to give you the chance of putting 
> error handling in __pure_virtual_called().

No, there should be a __pure_virtual_called() in the library.
It, in turn, should print an appropriate error message and abort.

It's there because by chicanery it is possible to call a pure virtual
in circumstances a compiler cannot detect.  For example:

	class A {
	public:
		A();
		virtual void f() = 0;
	};

No problem so far, right?  You can't create an A object, of course.

	void callf(A* ap)
	{
		ap->f();
	}

Still no problem.  Since you can't create an A object, ap must in
fact point to an object of a class derived from A, which in turn must
have defined an f() member.

Now look at this:

	A::A() { callf(this); }

Again there is no way for the compiler to see what's wrong.
The callf function might just plug data members of A, in
which case it would be harmless.  What it actually does, of
course, is to try to call the nonexistent f() member of the
A object!

So you see the point.  In principle you should not be allowed to
call a pure virtual but you can by trickery.  It is better to obtain
a clear diagnostic in that case than a random crash.
-- 
				--Andrew Koenig
				  ark@europa.att.com