> On Fri, 29 Sep 2000, Karl Nelson wrote:
> 
> > > 
> > > Hello,
> > > 
> > > While compiling LyX in fussy mode of compaq cxx (std strict_ansi -w0),
> > > the following warnings got printed:
> > 
> > > | cxx: Info: ../sigc++/basic_signal.h, line 139: destructor for base
> > > |           class "SigC::Signal_" is not virtual (D:basclsnondto)
> > > |           detected during instantiation of class "SigC::Signal0<void, Marsh
> > > >
> > > |                     [with Marsh=SigC::Marshal<void>]" at line 76 of
> > > |                     "../../lyx-devel/src/insets/inseterror.h"
> > > |   :public Signal_
> > > | ----------^
> > 
> > I think your compiler is incorrect on issuing thos warnings.  Virtual is only
> > required in the case where the derived class adds additional work such that
> > distroying the base class won't handle destruction of the derivved class.
> 
> Then again when you write the code you have no idea what weird things
> someone might derive from it.  Certainly within libsigc++'s codebase you
> know how it's being used.

Well, these are basically closed classes.  The derive just from common
base classes just so that they can group some common functionality.  It
is kind of like deriving from an STL list or an auto_ptr.  As a closed
class you do not place virtuals there as they should are not intended
as classes which you can take a pase pointer and get virtual behavior.

Remember these are just wrapper types.  They don't really hold anything
other that the typedefs used to interpret the data in the class properly.
 
> > Adding a virtual makes handles and signals virtual and thus requires
> > the compiler to implement typenodes and virtual tables for
> > what is intended to be a trivial class.  This will bloat out the
> > the library considerable.  
> 
> How much is considerably?

Considerably ranges from just a few Kbytes to many Meg depending on the
compiler and the usage.  For gtkmm this is in the many megs.  

Consider for a second how virtual interacts with templates. 

Assume I need to make a Handle virtual.  All Slot types come from
Handles.

If I make a virtual function in the class then I am saying this class
can be treated the same in a base class.  That means this class must be
unique.  This means I need
  - a typenode for use with typeinfo (name of this class and other id)
  - a vtable fragment to hold this new virtual dtor.
  - dynamic casting tables so that I can cast from the base to this unique class.
It must meet this for every Slot type.  Now each instantation of the class
is a unique type.  Thus every combination of arguments and return types
will cause a new set of functions.

It gets worse.  Some compilers do not know how to share symbols when compiled
with templates in multiple object files.  Worse, virtuals incounted in templates
must be in the header thus they must be instancated every time they are seen in
all files using that header.  There are hundreds of types in gtk--.  This means
for every object file must compile the virtuals for all those types and place
them in the object file.  

Okay, that looks bad by there is still worse things to come.  Egcs on some platforms
like HP-UX could not merge duplicated symbols generated from templates on library
builds.  Thus every symbol in the library is a symbol in the object file.  If the
library contains 10 object files it can get 10 copies of all of the virtual tables
from all of the symbols in the header.  Boom, a moderate library like Gtk-- grows
from 5M to 25M.  Similar holds for applications.

This can be enormous.  Using virtuals is thus quite literally not an option for
me.  And what do we gain for this virtuals.  Ablity to cast a slot from
type to type, not useful as you never change a slot to anything other than
what it is. I get typeinfo which is of very little use because the base
class is never used directly.  In other words, you pay a large memory cost to the 
binary for no real increase in functionality.


> > Since this was actually the intended behavior is there any way to 
> > override the warning?
> 
> The compiler warning flag that was used isn't used for our standard
> compilation with that compiler and is just a --be-extremely-picky flag
> used for testing.

Okay.  Hopefully understanding what we avoided which forces us to 
use classes in such a way that we get warnings like that will show
why sometimes --be-extremely-picky isn't always the right thing.  :-)
I will of course try on the next version to avoid public inheritance
of those classes and document what classes are final.

Hope this clears things up a bit. 

--Karl 

Reply via email to