[comp.lang.c++] Virtual Functions

gjditchfield@watrose.UUCP (12/12/86)

C++ seems to be generating code that cc won't accept. Am I doing something
wrong? 

This code was taken from section 7.2.8 of The Book.
------------
#include <stream.h>
struct employee {
    employee*	next;
    char*	name;
    short	department;
    virtual void print();
    };
void employee::print()
{   cout << name << "\t" << department << "\n";
    }
struct manager:employee {
    employee*	group;
    short	level;
    void	print();
    };
void manager::print()
{   employee::print();
    cout << "\tlevel" << level << "\n";
    }
void f(employee* ll)
{   for (; ll; ll=ll->next)
	ll->print();
    }
main()
{   employee e;
    e.name = "j.brown";
    e.department = 1234;
    manager m;
    m.name = "j.smith";
    m.level = 2;
    m.next = &e;
    f(&m);
    }
----------------
When I run it through C++, I get these error messages from cc:
"virt.cc", line 22: illegal function
"virt.cc", line 22: illegal function
where line 22 is "ll->print()" in function f. (The local support people
have set things up so that C++ files must have names ending in .cc.)

C++'s output, slightly prettified, looks like this:
----------------
#line 1 "virt.cc"

/* <<cfront 05/20/86>> */
//  ...

#line 20 "virt.cc"
int f (_auto_ll )struct employee *_auto_ll ;
{ 
	for(;_auto_ll ;_auto_ll = _auto_ll -> _employee_next )
#line 22 "virt.cc"
		(*(((int (*)())(*_auto_ll -> _employee__vptr ))))
		(*(((int (*)())(*_auto_ll -> _employee__vptr ))))( _auto_ll) ;
};
---------------
(I have broken the output for line 22 in two, for clarity.) The expression
referring to _employee__vptr seems to be meant to retrieve a pointer to the
appropriate print() routine, but I don't see why the expression should be
generated twice!

I would be delighted to find out that this is all my fault. Comments?
-- 
-------------------------------------------------------------------------------
Glen Ditchfield                      {watmath,utzoo,ihnp4}!watrose!gjditchfield
Dept of Computer Science, U of Waterloo         (519) 885-1211 x6658
Waterloo, Ontario, Canada
"Flame not, lest thou be singed" - Mr. Protocol

gjditchfield@watrose.UUCP (12/12/86)

One more thing: if I take out one of those two expressions referring to
vtbl and give the result to cc, the program works.

-- 
-------------------------------------------------------------------------------
Glen Ditchfield                      {watmath,utzoo,ihnp4}!watrose!gjditchfield
Dept of Computer Science, U of Waterloo         (519) 885-1211 x6658
Waterloo, Ontario, Canada
"Flame not, lest thou be singed" - Mr. Protocol

stephen@comp.lancs.ac.uk (Stephen J. Muir) (12/17/86)

Please state what version of C++ you're using.  Also, what O/S and M/C.
-- 
EMAIL:	stephen@comp.lancs.ac.uk	| Post: University of Lancaster,
UUCP:	...!mcvax!ukc!dcl-cs!stephen	|	Department of Computing,
Phone:	+44 524 65201 Ext. 4120		|	Bailrigg, Lancaster, UK.
Project:Alvey ECLIPSE Distribution	|	LA1 4YR

coatta@ubc-csgrads.uucp (Terry Coatta) (12/09/87)

I have been working on a set of generic list routines (as a way of
learning c++).  The method I have chosen to use is to supply a
class Link, from which the user can derive (publicly) his own
classes.  Since the class List functions use parameters of
type Link& for the most part, the user can simply pass items
of his own class to them.

The problem that I have encountered is that within the the List
class I want to provide a function which copies a list.  I originally
thought I could do this by:

     .
     .
     newlink = new Link(current);
     newlistprev->next = newlink;
     .
     .

that is, I would scan down the current list using the new operator
to duplicate nodes for me (via the Link::Link(Link&) constructor).
Then I realized that this would not work since that constructor
would not know how to copy the user's data.  It seems like the
Link class has to have a virtual function Duplicate() which
duplicates an instance.  The user derived class would have to
contain a Duplicate() function which would duplicate its own
data appropriately, and then call Link::Duplicate to ensure that
its duplication was handled correctly.

Is this more or less correct?  Does anybody have other suggestions?
I realize that there are other methods of approaching the
generic list problem, but this is the one I would like to use.

Terry Coatta
Dept. of Computer Science, UBC, Vancouver BC, Canada
coatta@grads.cs.ubc.cdn

`What I lack in intelligence, I more than compensate for with stupidity'

 

vkar@ihlpa.ATT.COM (Thayalan) (09/16/88)

In article <544*metz@iam.unibe.ch>, metz@iam.unibe.ch (Igor Metz) writes:
> .....
> If I rewrite the virtual declaration to
>   virtual void pprint() {}; // empty function body
> everything works fine. Is this a bug in the book, or am I doing something
> wrong?
You must define the virtual function in the base class. This is
exactly what you are doing to make it work correctly. 
The reference manual in Stroustrup's book clearly states this.
See page 278 in the book(English language version).
So therefore, the answer is, it's not a bug.

K. Thayalan

ericg@ucschu.ucsc.edu (Eric Goodman) (02/02/91)

In article <1991Jan29.221121.20642@odin.corp.sgi.com> linton@sgi.com (Mark 
Linton) writes:
> As for virtual functions, if you can't live with cost of a virtual 
function call
> you are unlikely to be happy with the cost of a direct function call.  A 
virtual
> function call typically adds a few memory references on top of what is 
likely
> a considerably more expensive operation, involving register save/restore 
and
> a branch.

There is more than the indirect reference.  There is the virtual function 
table which must be maintained for each object.  If you are dealing with 
many (thousands) of small (2-4 int) objects, by using virtual functions 
you are adding at least 25%-50% extra size to your objects (assuming ints 
and the index into the virtual function table to be equal in size - it's 
probably worse than that).  

This leads into my question: when I declare a class with virtual functions 
how much memory am I losing per object?  I was originally given to 
understand that for each virtual function a class maintains an index into 
a virtual function table, meaning extra memory size required is roughly 
proportional to the number of virtual functions.  But thinking about it, 
that sounds too inefficient, so it should be something like a pointer to a 
virtual function table is created, meaning each object created uses extra 
memory for having virtual functions, but the amount of memory lost per 
object is constant whether one or several virtual functions are used in 
the class.  

Who wants to straighten me out?  E-mail replies appreciated, or post and 
e-mail (I don't always get postings).

Thanks 

Eric Goodman, UC Santa Cruz

ericg@ucschu.ucsc.edu                              ericg@ucschu.bitnet
Eric_Goodman.staff@macmail.ucsc.edu      ...!ucbvax!ucscc!ucschu!ericg