Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Cost of inheriting an interface.

1 view
Skip to first unread message

Leigh McRae

unread,
Aug 31, 2002, 2:09:36 PM8/31/02
to
What is the cost of using virtual inheritance of a base class that is
abstract? Such as

class X_IObject
{
virtual void onUpdate() = 0;
virtual void onRender() = 0;
};


Leigh McRae


Andrey Tarasevich

unread,
Aug 31, 2002, 2:45:43 PM8/31/02
to
> ...

This is all implementation defined and compiler specific.

Instances of classes that have virtual bases will usually occupy more
storage then instances of classes that have the same non-virtual bases.

Virtual inheritance usually makes some negative performance impact on such
operations as accessing virtual base class member through a pointer to
derived class. Class 'X_IObject' in your posting doesn't contain any data
members and non-abstract member functions. For this reason, in this case it
is rather unlikely that you'll pay any performance costs because of virtual
inheritance alone.

However, if you are using virtual inheritance, then you are probably
planning to use multiple inheritance somewhere in the class hierarchy. The
multiple inheritance may have more or les noticeable negative prerformance
impact on virtual function calls.

I'm not sure that I covered everything here and, once again, it is compiler
specific. I you really want to know - experiment with your compiler, read
the documentation, maybe take a look at the generated assembly code.

--
Best regards,
Andrey Tarasevich
Brainbench C and C++ Programming MVP

Ioannis Vranos

unread,
Aug 31, 2002, 2:41:59 PM8/31/02
to
"Leigh McRae" <leigh...@cogeco.ca> wrote in message
news:XE7c9.38857$Bj.36...@read2.cgocable.net...


The time cost is almost the same as the time cost of calling a member
function. Importantly, the time cost is the same independently from
the depth of abstraction. So the time cost is the same either you have
an hierarchy of depth of 100 classes, or 1000 classes.


--
Ioannis

* Ioannis Vranos
* Programming pages: http://www.noicys.cjb.net
* Alternative URL: http://run.to/noicys


Victor Bazarov

unread,
Aug 31, 2002, 2:48:06 PM8/31/02
to
"Leigh McRae" <leigh...@cogeco.ca> wrote...


You have to define "cost".

Victor
--
Please remove capital A's from my address when replying by mail


Rolf Magnus

unread,
Aug 31, 2002, 2:57:04 PM8/31/02
to
Ioannis Vranos wrote:

> The time cost is almost the same as the time cost of calling a member
> function. Importantly, the time cost is the same independently from
> the depth of abstraction. So the time cost is the same either you have
> an hierarchy of depth of 100 classes, or 1000 classes.

Does the standard guarantee this?

Leigh McRae

unread,
Aug 31, 2002, 3:07:43 PM8/31/02
to
Your right. The question was VERY poorly written. Sorry.

I have the X_IObject as an interface that I want to use in many classes.
Also the X_IObject will likely be inherited more than once in a class. In
the following examples all the classes that start with X_I are abstract
classes (all pure virtual functions and no data).

class X_BaseObject : public X_IObject
{
// Concrete with data and member functions to implement X_IObject
// This is my default implementation but I am thinking that later on I
will
// want a more lightweight (data wise) version. So I made an interface.
};

class X_IPlayer : public X_IObject
{
// All players need to support X_IObject but they might not use the same
// data as X_BaseObject. So I made an interface :)
};

class X_LocalPlayer : public X_IPlayer, public X_IObject, public
X_BaseObject
(
// Concrete with data and member functions to implement X_IPlayer. For
this
// type of player I can use X_BaseObject to implement X_IObject. Thing
is
// now I have X_IObject twice.
);

Now I could inherit X_IObject as virtual and I think this will work but is
this madness? Just down right crappy design? I am really into using
interfaces these days but the problem is that when you have a hammer
everything looks like a nail.

Leigh

"Victor Bazarov" <vAba...@dAnai.com> wrote in message
news:Gb8c9.308925$UU1.54637@sccrnsc03...

Victor Bazarov

unread,
Aug 31, 2002, 3:35:06 PM8/31/02
to
"Leigh McRae" <leigh...@cogeco.ca> wrote...

> I have the X_IObject as an interface that I want to use in many classes.
> Also the X_IObject will likely be inherited more than once in a class. In
> the following examples all the classes that start with X_I are abstract
> classes (all pure virtual functions and no data).
>
> class X_BaseObject : public X_IObject
> {
> // Concrete with data and member functions to implement X_IObject
> // This is my default implementation but I am thinking that later on I
> will
> // want a more lightweight (data wise) version. So I made an
interface.
> };
>
> class X_IPlayer : public X_IObject
> {
> // All players need to support X_IObject but they might not use the
same
> // data as X_BaseObject. So I made an interface :)
> };
>
> class X_LocalPlayer : public X_IPlayer, public X_IObject, public
> X_BaseObject
> (
> // Concrete with data and member functions to implement X_IPlayer.
For
> this
> // type of player I can use X_BaseObject to implement X_IObject.
Thing
> is
> // now I have X_IObject twice.

Thrice, acutally.

> );
>
> Now I could inherit X_IObject as virtual and I think this will work but
is
> this madness?

Yes, it would.

> Just down right crappy design? I am really into using
> interfaces these days but the problem is that when you have a hammer
> everything looks like a nail.

Well, if you use C++ inheritance, everything looks like a class.
That's not a bad thing.

Now, about your design. I don't know whether it was intentional
or not, but I don't understand the need for X_LocalPlayer to
inherit X_BaseObject _and_ X_IObject. X_BaseObject already
inherits X_IObject and implements the interface, doesn't it?

Just this week we discussed a similar thing with our colleagues.

struct IFoo // abstract class
{
public:
virtual void foo() = 0;
};

class Foo : public IFoo // implements it
{
public:
void foo();
};

class IFooEx : public IFoo // additional interface, new abstract
{
public:
virtual void bar() = 0;
};

Now I want to implement IFooEx but use Foo's implementation of
IFoo:

class FooEx : public IFooEx, public Foo
{
public:
void bar();
};

[Note: this looks _exactly_ like the example you've given]

The compiler would not let me instantiate FooEx because it has
_two_ IFoo::foo() functions which are pure. And for some reason
it doesn't matter that there can be only one _function_ body and
seemingly there is no ambiguity, is there? Whether the ambiguity
exists or doesn't, it can be solved by virtually inheriting IFoo
in IFooEx and in Foo.

I consider it a quirk in the language, bit the compiler is not
going to be easier to implement if we impose an additional rule
on it: "if the class has no members and all functions are
pure, it cannot be ambiguous"... It's not the only quirk and
there is a solution, so why complain, right? :-)

Coming back to your original post, what _is_ the "cost" you're
referring to?

Andrey Tarasevich

unread,
Aug 31, 2002, 3:53:12 PM8/31/02
to

Why do you want to inherit X_IObject as virtual base class? You must
understand that event though you have several subobjects of type X_IObject
inside your X_LocalPlayer object, each and every of them can act as
fully-functional interface to the X_LocalPlayer. Class X_IObject contains no
data members so the speed/memory cost of having several of them will be very
small.

One thing the virtual inheritance will give you here is the ability to use
pointers to X_IObject to identify instances of X_LocalPlayer class. In case
of virtual inheritance, if you have two pointers to X_IObject interface that
compare equal, then you can be sure that these two interfaces access the
same X_LocalPlayer instance. Otherwise, if the pointers are different, then
you can be sure that these two interfaces access different X_LocalPlayer
instances. If you don't use virtual inheritance, this simple rule will not
work. Decide whether this feature can be useful in your project.

Victor Bazarov

unread,
Aug 31, 2002, 3:57:24 PM8/31/02
to
"Andrey Tarasevich" <andreyta...@hotmail.com> wrote in message
news:3D711EA8...@hotmail.com...

Because it doesn't work otherwise:
--------------------------------------------------------
#define virtual // comment this out to see the effect of
// declaring virtual inheritance

struct IFoo // abstract class
{
public:
virtual void foo() = 0;
};

class Foo : public virtual IFoo // implements it
{
public:
void foo();
};

class IFooEx : public virtual IFoo // additional interface, new abstract


{
public:
virtual void bar() = 0;
};

class FooEx : public IFooEx, public Foo
{
public:
void bar();
};

int main()
{
FooEx fx;
fx.foo(); // if you didn't comment out the macro at the top,
// you should get an error here.
fx.bar();
}

--------------------------------------------------------

> You must
> understand that event though you have several subobjects of type X_IObject
> inside your X_LocalPlayer object, each and every of them can act as
> fully-functional interface to the X_LocalPlayer.

...and makes any attempt to resolve a function from it _ambiguous_.

> Class X_IObject contains no
> data members so the speed/memory cost of having several of them will be
very
> small.

That's not the problem.

> One thing the virtual inheritance will give you here is the ability to use
> pointers to X_IObject to identify instances of X_LocalPlayer class.

That's not the problem.

You missed the point, I believe.

Leigh McRae

unread,
Aug 31, 2002, 4:04:06 PM8/31/02
to

"Victor Bazarov" <vAba...@dAnai.com> wrote in message
news:KT8c9.76280$_91....@rwcrnsc51.ops.asp.att.net...


So I should rethink the whole design?


>
> > Just down right crappy design? I am really into using
> > interfaces these days but the problem is that when you have a hammer
> > everything looks like a nail.
>
> Well, if you use C++ inheritance, everything looks like a class.
> That's not a bad thing.
>
> Now, about your design. I don't know whether it was intentional
> or not, but I don't understand the need for X_LocalPlayer to
> inherit X_BaseObject _and_ X_IObject. X_BaseObject already
> inherits X_IObject and implements the interface, doesn't it?


Yuppers. Little X_IObject crazy on my part :)


>
> Just this week we discussed a similar thing with our colleagues.
>
> struct IFoo // abstract class
> {
> public:
> virtual void foo() = 0;
> };
>
> class Foo : public IFoo // implements it
> {
> public:
> void foo();
> };
>
> class IFooEx : public IFoo // additional interface, new abstract
> {
> public:
> virtual void bar() = 0;
> };
>
> Now I want to implement IFooEx but use Foo's implementation of
> IFoo:
>
> class FooEx : public IFooEx, public Foo
> {
> public:
> void bar();
> };
>
> [Note: this looks _exactly_ like the example you've given]

Agreeded. So did you end up using it by using virtual inheritance? I made
a test case and it work. VC++ gives a warning and I tend to treat warning
as errors. So this worries me. It seems like the right thing to do is have
different interfaces have concrete classes inherit from them but I am now
wondering if this is just an easy out for poor design.

>
> The compiler would not let me instantiate FooEx because it has
> _two_ IFoo::foo() functions which are pure. And for some reason
> it doesn't matter that there can be only one _function_ body and
> seemingly there is no ambiguity, is there? Whether the ambiguity
> exists or doesn't, it can be solved by virtually inheriting IFoo
> in IFooEx and in Foo.
>
> I consider it a quirk in the language, bit the compiler is not
> going to be easier to implement if we impose an additional rule
> on it: "if the class has no members and all functions are
> pure, it cannot be ambiguous"... It's not the only quirk and
> there is a solution, so why complain, right? :-)
>
> Coming back to your original post, what _is_ the "cost" you're
> referring to?

I thought I removed cost from the second post :) since it isn't really
what I was asking. I am more interested in what kind of hurt I am heading
into for this. I have already seen that each interface cost 4bytes in VC. I
wouldn't expect there to be any kind of speed hit. I think I need to
redesign the heirarchy and make some kind of solid stand instead of trying
to be so flexable...

Leigh

Leigh McRae

unread,
Aug 31, 2002, 4:18:44 PM8/31/02
to
>
> Why do you want to inherit X_IObject as virtual base class? You must
> understand that event though you have several subobjects of type X_IObject
> inside your X_LocalPlayer object, each and every of them can act as
> fully-functional interface to the X_LocalPlayer. Class X_IObject contains
no
> data members so the speed/memory cost of having several of them will be
very
> small.

It won't compile unless I do. Though I am not sure why that is. Here is
a small test app I wired up. It complains that onRender() isn't defined for
Player. Otherwise I see your point. BTW do you think this is bad desgin?

#include <stdio.h>
//==========================================================================
====
//==========================================================================
====
class IObject
{
public:
virtual ~IObject() { }

virtual void onRender() = 0;
};

//==========================================================================
====
//==========================================================================
====
class IPlayer : public IObject
{
public:
virtual ~IPlayer() { }

virtual void onUpdate() = 0;

};
//==========================================================================
====
//==========================================================================
====
class BaseObject : public IObject
{
public:
void onRender()
{
printf( "onRender()\n" );
}
};
//==========================================================================
====
//==========================================================================
====
class Player : public IPlayer, public BaseObject
{
public:
void onUpdate()
{
printf( "onUpdate()\n" );
}
};
//==========================================================================
====
//==========================================================================
====
int main(int argc, char* argv[])
{
Player player;
BaseObject object;
int cbSize;

cbSize = sizeof( player );
cbSize = sizeof( object );

return 0;
}


>
> One thing the virtual inheritance will give you here is the ability to use
> pointers to X_IObject to identify instances of X_LocalPlayer class. In
case
> of virtual inheritance, if you have two pointers to X_IObject interface
that
> compare equal, then you can be sure that these two interfaces access the
> same X_LocalPlayer instance. Otherwise, if the pointers are different,
then
> you can be sure that these two interfaces access different X_LocalPlayer
> instances. If you don't use virtual inheritance, this simple rule will not
> work. Decide whether this feature can be useful in your project.

I suspect it would be required. It looks like I am getting closer to my
scope of the question :) The whole scenario changes if I wasn't talking
about pure abstract classess. When you look at it there should be no benifit
from inheriting them virtually? This leads me to think that my sample
should compile and that its not all that bad design.

Leigh

Andrey Tarasevich

unread,
Aug 31, 2002, 4:26:14 PM8/31/02
to
Victor Bazarov wrote:
>>
>>Why do you want to inherit X_IObject as virtual base class?
>
>
> Because it doesn't work otherwise:

_Your_ code doesn't work otherwise. Your code doesn't compile because

1) the most derived object doesn't provide the final overrider for certain
pure virtual functions
2) the function name in 'fx.foo()' is ambiguous

That's your faults, not the design faults. Coorrect the problems and
everything will work fine:

...


class FooEx : public IFooEx, public Foo
{
public:
void bar();

void foo() { Foo::foo(); }
};
...

>
>>You must
>>understand that event though you have several subobjects of type X_IObject
>>inside your X_LocalPlayer object, each and every of them can act as
>>fully-functional interface to the X_LocalPlayer.
>
>
> ...and makes any attempt to resolve a function from it _ambiguous_.
>

Wrong. No ambiguity here.

>>One thing the virtual inheritance will give you here is the ability to use
>>pointers to X_IObject to identify instances of X_LocalPlayer class.
>
> That's not the problem.

Nobody says that' s the problem. That one of the design considerations that
should be taken into account.

> You missed the point, I believe.

I believe, you don't see the _whole_ point.

Andrey Tarasevich

unread,
Aug 31, 2002, 4:34:27 PM8/31/02
to
Leigh McRae wrote:

> It won't compile unless I do.

> class Player : public IPlayer, public BaseObject


> {
> public:
> void onUpdate()
> {
> printf( "onUpdate()\n" );
> }
> };


You need to give the compiler a little help here. Do this

class Player : public IPlayer, public BaseObject
{
public:
void onUpdate()
{
printf( "onUpdate()\n" );
}

void OnRender()
{
BaseObject::OnRender();
}
};

and everything will compile.

> Though I am not sure why that is.

See my reply to Victor for explanation about why it doesn't compile.

> BTW do you think this is bad desgin?

What we see here is just a small piece of your design. It's hard to make the
final verdict :)

>
>>you can be sure that these two interfaces access different X_LocalPlayer
>>instances. If you don't use virtual inheritance, this simple rule will not
>>work. Decide whether this feature can be useful in your project.
>
> I suspect it would be required.

Use virtual inheritance then.

Victor Bazarov

unread,
Aug 31, 2002, 4:32:26 PM8/31/02
to
"Leigh McRae" <leigh...@cogeco.ca> wrote...

>
> "Victor Bazarov" <vAba...@dAnai.com> wrote in message
> news:KT8c9.76280$_91....@rwcrnsc51.ops.asp.att.net...
> > Just this week we discussed a similar thing with our colleagues.
> >
> > struct IFoo // abstract class
> > {
> > public:
> > virtual void foo() = 0;
> > };
> >
> > class Foo : public IFoo // implements it
> > {
> > public:
> > void foo();
> > };
> >
> > class IFooEx : public IFoo // additional interface, new abstract
> > {
> > public:
> > virtual void bar() = 0;
> > };
> >
> > Now I want to implement IFooEx but use Foo's implementation of
> > IFoo:
> >
> > class FooEx : public IFooEx, public Foo
> > {
> > public:
> > void bar();
> > };
> >
> > [Note: this looks _exactly_ like the example you've given]
>
> Agreeded. So did you end up using it by using virtual inheritance? I
made
> a test case and it work. VC++ gives a warning and I tend to treat warning
> as errors. So this worries me.

We did end up with virtual inheritance. And we will see that
warning. What worries me is our stubborness about not trying
any other compilers. VC++'s quirks are beggining to get to me.
Just like that level 2 "informative" warning...

> It seems like the right thing to do is have
> different interfaces have concrete classes inherit from them but I am now
> wondering if this is just an easy out for poor design.

Abstract interfaces and concrete implementations are the basis
for polymorphism. How else would you do it?

> > Coming back to your original post, what _is_ the "cost" you're
> > referring to?
>
> I thought I removed cost from the second post :) since it isn't really
> what I was asking. I am more interested in what kind of hurt I am heading
> into for this.

AFAIK, none. We at our place are thinking of introducing
a policy: always inherit abstract classes (interfaces) virtually.

> I have already seen that each interface cost 4bytes in VC.

But that cost shouldn't increase in derived classes. It is
brought about by usually implementing virtual functions mechanism
through a table of pointers to them (vtbl)...

> I
> wouldn't expect there to be any kind of speed hit.

There is no penalty in virtually deriving versus simply deriving.

> I think I need to
> redesign the heirarchy and make some kind of solid stand instead of trying
> to be so flexable...

That's up to you, of course.

chuck starchaser

unread,
Aug 31, 2002, 4:34:42 PM8/31/02
to

In most implementations, inheriting an abstract class with no data
members, whether virtually or not, is much reduced. I'd be more
concerned about deriving from concrete classes.

There's a little known OO language called Sather, which was designed
with highest concern for executable performance. To that end, they
decided to prohibit concrete inheritance. When working with Sather,
you create abstract hyerarchies as deep as you want; but once you
fully implement a derived class, you can inherit no further.
I found that restriction so inspiring that I've made it my religion to
NEVER inherit from a concrete class in C++; and haven't had to violate
my rule yet.

But it depends on what kind of polymorphism you want to have.

Say you have abstract class A, then B and C deriving from A,
then D and E derivin from B. Now, will you ever have a pointer of type
B through which you must access a D or an E polymorphically? If the
answer is No, and you can just make all your pointers of type A, then
you could "flatten" your hyerarchy: have all of B,C,D,E inherit from
abstract base A, get rid of virtual, and simplify your life.


Ioannis Vranos

unread,
Aug 31, 2002, 5:04:36 PM8/31/02
to
"Rolf Magnus" <rama...@t-online.de> wrote in message
news:akr3hd$6i0$04$1...@news.t-online.com...


I checked the standard and i did not find any such guarantee. But
Stroustrup mentions this in TC++PL 3 (and god doesn't mention things
without reason) and also as far as i know the usual implementation of
a v-table (used in virtual functions) is an array of pointers to
functions, and the function is accessed directly using an index. god
explicitly mentions that the lookup mechanism of that index has the
same time cost for all indexes.


Here is what Stroustrup says:


"The C++ Programming Language" 3rd Edition or Special edition (also
known as the C++ bible).


On page 37:

"The functions in the vtbl allow the object to be used correctly even
when the size of the object and the layout of its data are unknown to
the caller. All the caller needs to know is the location of the vtbl
in a Stack [That was an example] and the index used for each virtual
function. This virtual call mechanism can be made essentially as
efficient as the "normal function call" mechanism. Its space overhead
is one pointer in each object of a class with virtual functions plus
one vtbl for each such class".


On page 312:

"It is worth remembering that the traditional and obvious
implementation of a virtual function call is simply an indirect
function call (2.5.5), so efficiency concerns should not deter anyone
from using a virtual function where an ordinary function call would be
acceptably efficient".


On page 324:

"After all, a virtual function call is cheap and independent of the
kind of the abstraction barrier it crosses. It costs no more to call a
member of an abstract class than to call any other virtual function".

Andrey Tarasevich

unread,
Aug 31, 2002, 5:16:03 PM8/31/02
to
Ioannis Vranos wrote:
> ...

> I checked the standard and i did not find any such guarantee. But
> Stroustrup mentions this in TC++PL 3 (and god doesn't mention things
> without reason) and also as far as i know the usual implementation of
> a v-table (used in virtual functions) is an array of pointers to
> functions, and the function is accessed directly using an index. god
> explicitly mentions that the lookup mechanism of that index has the
> same time cost for all indexes.
>

You probably missed the fact that the OP is asking about virtual
_inheritance_, not about virtual functions.

Siemel Naran

unread,
Aug 31, 2002, 5:16:49 PM8/31/02
to
"Leigh McRae" <leigh...@cogeco.ca> wrote in message news:XE7c9.38857

> What is the cost of using virtual inheritance of a base class that is

The space cost is small. The space cost is per class: Every class derived
from X_IObject inherits these 2 functions. I suppose you want a virtual
destructor too. So that's 3 functions altogether.

In common implementations, for each class X_IObject or a class derived from
it there will be a virtual table which gives the addresses of the 3 virtual
functions. So basically the virtual table will be an array of 3 pointers to
function. Say you have 10 classes derived from X_IObject and the X_IObject
itself, that's 11 virtual tables or 33 pointers to function (which is only
33*4=132 bytes on Intel). That's regardless of the number of X_IObject
objects or other objects, and these could run into thousands or millions of
bytes.

However, for any class there may be many identical copies of the virtual
table, so your memory usage may be more than the above. The exact number of
copies is implementation dependent. But I suppose that on common
implementations each DLL would have one copy of the virtual table.

Also, there is a per object cost. Each object will have a virtual pointer
(4 bytes on Intel) that points to the virtual table.


As for the time cost of using the virtual function, it is usually nothing at
all.

--
+++++++++++
Siemel Naran


Siemel Naran

unread,
Aug 31, 2002, 5:16:50 PM8/31/02
to
"Rolf Magnus" <rama...@t-online.de> wrote in message news:akr3hd$6i0$04

No, the standard does not garauntee it. But in all the implementations I've
seen, it is standard. The depth level of the hierarchy does not matter.
Thanks to the virtual table concept (which is not required by the standard
but all or most compilers do it), which gives a pointer directly to the
actual function to call.


However the time cost of calling a non-virtual function is usually less by
such a small amount. Calling a virtual function the system has to fetch the
virtual pointer which points to the virtual table. Then it fetch the
address of the function. And finally call that function by address.

It's not a big cost, but it is something. If your function does a lot of
stuff then the time in the virtual function overhead is negligible by
comparison. Say the overhead (of finding the virtual pointer, function,
calling by address) is 100 nanoseconds. But the cost in the function to do
everything else is 100,000 nanoseconds then the overhead is negligible.

But if the function is very simple like just increment an integer then the
cost is significant. The virtual function overhead is 100 nanoseconds, and
the function itself is 100 nanoseconds. That means the time to call the
function is doubled. If you call the function 1 million times you'll notice
the difference!

--
+++++++++++
Siemel Naran


Daniel T.

unread,
Aug 31, 2002, 5:26:30 PM8/31/02
to
"Leigh McRae" <leigh...@cogeco.ca> wrote:

Without seeing how the objects from these classes are used, it is hard
to say exactly what should be done. (With interfaces, the context is
everything.)

I would suggest you simplify your life. All X_IPlayers must implement
the X_IObject interface. You made this rule with you derived X_IPlayer
from X_IObject, so you don't need to derive from X_IObject yet again.
X_LocalPlayer has no reason to derive publicly from X_BaseObject, any
context that wants to use X_BaseObjects and X_LocalPlayers
polymorphically can hold them through X_IObject pointers. So you end up
with:

class X_LocalPlayer: public X_IPlayer, private X_BaseObject
{
public:
// Implement the X_IPlayer interface, which includes the
// X_IObject interface. For the latter, you just deligate to the
// X_BaseObject class.
};

Ioannis Vranos

unread,
Aug 31, 2002, 8:24:01 PM8/31/02
to
"Siemel Naran" <Sieme...@KILL.att.worldnet.net> wrote in message
news:5nac9.44991$Ke2.3...@bgtnsc04-news.ops.worldnet.att.net...


And as god mentions in TC++PL if you stored the type information
yourself inside the class the space cost would be probably larger (or
at least the same).

Ioannis Vranos

unread,
Aug 31, 2002, 8:21:13 PM8/31/02
to
"Andrey Tarasevich" <andreyta...@hotmail.com> wrote in message
news:3D713213...@hotmail.com...

>
> You probably missed the fact that the OP is asking about virtual
> _inheritance_, not about virtual functions.


If you mean having a virtual base, this isn't the case. Notice his
example:

"
class X_IObject
{
virtual void onUpdate() = 0;
virtual void onRender() = 0;
};
"

--

Neil Butterworth

unread,
Aug 31, 2002, 8:39:56 PM8/31/02
to
"Ioannis Vranos" <noi...@spammers.get.lost.hotmail.com> wrote in message
news:10308396...@athprx02.forthnet.gr...

> "Andrey Tarasevich" <andreyta...@hotmail.com> wrote in message
> news:3D713213...@hotmail.com...
> >
> > You probably missed the fact that the OP is asking about virtual
> > _inheritance_, not about virtual functions.
>
>
> If you mean having a virtual base, this isn't the case. Notice his
> example:
>
> "
> class X_IObject
> {
> virtual void onUpdate() = 0;
> virtual void onRender() = 0;
> };

Better still, notice his original question:

"What is the cost of using virtual inheritance of a base class that is
abstract?"

I realise you don't know too much about C++, but you can read? Does the
phrase "virtual inheritance" in the question possibly suggest that the OP is
asking about ... virtual inheritance?

NeilB


Victor Bazarov

unread,
Aug 31, 2002, 9:09:18 PM8/31/02
to
"Ioannis Vranos" <noi...@spammers.get.lost.hotmail.com> wrote...

> "Andrey Tarasevich" <andreyta...@hotmail.com> wrote in message
> news:3D713213...@hotmail.com...
> >
> > You probably missed the fact that the OP is asking about virtual
> > _inheritance_, not about virtual functions.
>
>
> If you mean having a virtual base, this isn't the case. Notice his
> example:
>
> "
> class X_IObject
> {
> virtual void onUpdate() = 0;
> virtual void onRender() = 0;
> };
> "


Do you _know_ what virtual inheritance is, what it is for, and
how it is achieved in the language?

Leigh McRae

unread,
Aug 31, 2002, 10:28:03 PM8/31/02
to

"Andrey Tarasevich" <andreyta...@hotmail.com> wrote in message
news:3D712666...@hotmail.com...

> Victor Bazarov wrote:
> >>
> >>Why do you want to inherit X_IObject as virtual base class?
> >
> >
> > Because it doesn't work otherwise:
>
> _Your_ code doesn't work otherwise. Your code doesn't compile because
>
> 1) the most derived object doesn't provide the final overrider for certain
> pure virtual functions
> 2) the function name in 'fx.foo()' is ambiguous
>
> That's your faults, not the design faults. Coorrect the problems and
> everything will work fine:
>
> ...
> class FooEx : public IFooEx, public Foo
> {
> public:
> void bar();
> void foo() { Foo::foo(); }
> };
> ...
>

Ok. Gotcha. I can see how this works but I was hoping that I wouldn't
have to wire all the member functions. Its not like its the biggest job but
IMHO its starts to get into the cut and paste type of coding. For this
matter I could inherit Foo private or even have Foo is a member variable.
All of these come close to being the same since objects should only be
accessed through an interface. I can't see ever having to cast to a Foo.

While we are on the topic. Which would be faster? Your version of FooEx
or this one?

class FooEx : public IFooEx, public IFoo
{
private:
Foo m_Foo;
public:
void bar();
void foo() { m_Foo.foo(); }
};

Leigh McRae

Leigh McRae

unread,
Aug 31, 2002, 10:32:45 PM8/31/02
to

"Daniel T." <notda...@gte.net> wrote in message
news:notdanielt3-94A5...@news.bellatlantic.net...

> "Leigh McRae" <leigh...@cogeco.ca> wrote:
>
>
> I would suggest you simplify your life. All X_IPlayers must implement
> the X_IObject interface. You made this rule with you derived X_IPlayer
> from X_IObject, so you don't need to derive from X_IObject yet again.
> X_LocalPlayer has no reason to derive publicly from X_BaseObject, any
> context that wants to use X_BaseObjects and X_LocalPlayers
> polymorphically can hold them through X_IObject pointers. So you end up
> with:
>
> class X_LocalPlayer: public X_IPlayer, private X_BaseObject
> {
> public:
> // Implement the X_IPlayer interface, which includes the
> // X_IObject interface. For the latter, you just deligate to the
> // X_BaseObject class.
> };

This is basiclly what Andrey suggested. First I think I will rethink the
whole thing to be sure I am not making more interfaces than needed. If not
then I suspect that inheriting X_BaseObject as private would be the best OO
design.

Leigh


Leigh McRae

unread,
Aug 31, 2002, 10:35:52 PM8/31/02
to

"chuck starchaser" <chuck_st...@mail.com> wrote in message
news:g292nu4d1pk3ptvc1...@4ax.com...

> On Sat, 31 Aug 2002 14:09:36 -0400, "Leigh McRae"
> <leigh...@cogeco.ca> wrote:
>
> > What is the cost of using virtual inheritance of a base class that is
> >abstract? Such as
> >
> >class X_IObject
> >{
> > virtual void onUpdate() = 0;
> > virtual void onRender() = 0;
> >};
>
> In most implementations, inheriting an abstract class with no data
> members, whether virtually or not, is much reduced. I'd be more
> concerned about deriving from concrete classes.
>
> There's a little known OO language called Sather, which was designed
> with highest concern for executable performance. To that end, they
> decided to prohibit concrete inheritance. When working with Sather,
> you create abstract hyerarchies as deep as you want; but once you
> fully implement a derived class, you can inherit no further.
> I found that restriction so inspiring that I've made it my religion to
> NEVER inherit from a concrete class in C++; and haven't had to violate
> my rule yet.

I like this idea and I think I will add it to my on going design style. I
have found that it is one thing to say you code in C++ and another to say
that you know what your doing. Its information like this that helps be come
closer to knowing what I am doing :)

Leigh McRae

Leigh McRae

unread,
Aug 31, 2002, 10:36:59 PM8/31/02
to
I would like to thank all of you for some good help, dispite my poorly
composed quetion. I think I managed to learn a thing or two.

Leigh

"Leigh McRae" <leigh...@cogeco.ca> wrote in message

news:XE7c9.38857$Bj.36...@read2.cgocable.net...


> What is the cost of using virtual inheritance of a base class that is
> abstract? Such as
>
> class X_IObject
> {
> virtual void onUpdate() = 0;
> virtual void onRender() = 0;
> };
>
>

> Leigh McRae
>
>


Andrey Tarasevich

unread,
Aug 31, 2002, 11:05:01 PM8/31/02
to
chuck starchaser wrote:
> ...

> There's a little known OO language called Sather, which was designed
> with highest concern for executable performance. To that end, they
> decided to prohibit concrete inheritance. When working with Sather,
> you create abstract hyerarchies as deep as you want; but once you
> fully implement a derived class, you can inherit no further.
> I found that restriction so inspiring that I've made it my religion to
> NEVER inherit from a concrete class in C++; and haven't had to violate
> my rule yet.
> ...

And how is the notion of "abstract class" defined in Sather?

Victor Bazarov

unread,
Sep 1, 2002, 2:45:58 AM9/1/02
to
"Andrey Tarasevich" <andreyta...@hotmail.com> wrote...

> Victor Bazarov wrote:
> >>
> >>Why do you want to inherit X_IObject as virtual base class?
> >
> >
> > Because it doesn't work otherwise:
>
> _Your_ code doesn't work otherwise. Your code doesn't compile because

My code doesn't compile because you failed to read it carefully.
Go back and read the comments FCOL. It's not supposed to compile
unless you comment out the first line.

>
> 1) the most derived object doesn't provide the final overrider for certain
> pure virtual functions
> 2) the function name in 'fx.foo()' is ambiguous
>
> That's your faults, not the design faults. Coorrect the problems and
> everything will work fine:

You know, arrogance and inattentiveness is a bad combination.

Victor
--
Please remove capital As from my address when replying by mail


Andrey Tarasevich

unread,
Sep 1, 2002, 3:46:27 AM9/1/02
to
Victor Bazarov wrote:
>>>
>>>Because it doesn't work otherwise:
>>
>>_Your_ code doesn't work otherwise. Your code doesn't compile because
>
> My code doesn't compile because you failed to read it carefully.

In my post I stated the exact reason why your code doesn't compile (with
that #define at the beginning). I couldn't have possibly done that without
reading your code carefully.

> Go back and read the comments FCOL. It's not supposed to compile
> unless you comment out the first line.

So what? It doesn't compile without virtual inheritance, it does compile
with virtual inheritance. Are you implying that this is enough to justify
the use of virtual inheritance in this case? That's very strange reasoning,
to say the least. Something like "If your program crashes with 'Division by
zero' message, just replace all division operators with multiplication
operators and the problem will go away".

That's nonsense. You introduced this code trying to demonstrate that one or
more of the statements that I made are incorrect. According to you, the fact
that this code doesn't compile proves me wrong. All I'm saying is that it
doesn't prove me wrong and and it doesn't actually demonstrate anything
relevant. This code doesn't compile because it's ill-formed. Just add a line
or two as I suggested before and it will compile _without_ _virtual_
_inheritance_.

Rolf Magnus

unread,
Sep 1, 2002, 4:05:43 AM9/1/02
to
Siemel Naran wrote:

> However the time cost of calling a non-virtual function is usually less by
> such a small amount. Calling a virtual function the system has to fetch
> the
> virtual pointer which points to the virtual table. Then it fetch the
> address of the function. And finally call that function by address.

Actually, it's one dereferene more, because it fetches the pointer to the
vtable via a pointer to the object, which means that with a vtable, a
virtual function is called through something like a pointer to a pointer to
an indexed pointer to a function. Maybe even some more indexing or pointer
dereference for multiple inheritance. How much that costs probably is
system specific. I guess that the cost is higher e.g. on an x86 system
which has redicuously few registers than on a system with more registers.

> It's not a big cost, but it is something. If your function does a lot of
> stuff then the time in the virtual function overhead is negligible by
> comparison. Say the overhead (of finding the virtual pointer, function,
> calling by address) is 100 nanoseconds. But the cost in the function to
> do everything else is 100,000 nanoseconds then the overhead is negligible.

Sure. I don't want to say that virtual function are so slow that you should
never use them. But it's good to remember that they don't come without a
cost, as long as you know where that cost matters and where it doesn't.

> But if the function is very simple like just increment an integer then the
> cost is significant. The virtual function overhead is 100 nanoseconds,
> and
> the function itself is 100 nanoseconds. That means the time to call the
> function is doubled. If you call the function 1 million times you'll
> notice the difference!

Incrementing an integer is probably several times faster than calling a
virtual function.

chuck starchaser

unread,
Sep 1, 2002, 5:16:50 AM9/1/02
to
On Sat, 31 Aug 2002 20:05:01 -0700, Andrey Tarasevich
<andreyta...@hotmail.com> wrote:

>chuck starchaser wrote:
> > ...
>> There's a little known OO language called Sather, which was designed
>> with highest concern for executable performance. To that end, they
>> decided to prohibit concrete inheritance. When working with Sather,
>> you create abstract hyerarchies as deep as you want; but once you
>> fully implement a derived class, you can inherit no further.
>> I found that restriction so inspiring that I've made it my religion to
>> NEVER inherit from a concrete class in C++; and haven't had to violate
>> my rule yet.
>> ...
>
>And how is the notion of "abstract class" defined in Sather?

Long story. Sather has two types of inheritance: "type inheritance"
and "code inclusion". The two are orthogonal. But it works out more or
less to the same concept of C++ abstract class.

I don't remember their term for pure virtual function; maybe it was
"deferred". At least that's the term in Eiffel (and Sather is an early
branch off Eiffel.) As long as a class has one deferred function, it
cannot be instantiated, and is called a "partial" class. Once a class
is non-partial, it can be instantiated, but it can no longer be
derived, though I believe 'code' from it may still be extractable.

But don't quote me on it; it was years ago I looked at it.

chuck starchaser

unread,
Sep 1, 2002, 7:31:03 AM9/1/02
to
On Sat, 31 Aug 2002 21:16:50 GMT, "Siemel Naran"
<Sieme...@KILL.att.worldnet.net> wrote:

>"Rolf Magnus" <rama...@t-online.de> wrote in message news:akr3hd$6i0$04
>> Ioannis Vranos wrote:
>>
>> > The time cost is almost the same as the time cost of calling a member
>> > function. Importantly, the time cost is the same independently from
>> > the depth of abstraction. So the time cost is the same either you have
>> > an hierarchy of depth of 100 classes, or 1000 classes.
>>
>> Does the standard guarantee this?
>
>No, the standard does not garauntee it. But in all the implementations I've
>seen, it is standard. The depth level of the hierarchy does not matter.
>Thanks to the virtual table concept (which is not required by the standard
>but all or most compilers do it), which gives a pointer directly to the
>actual function to call.
>
>However the time cost of calling a non-virtual function is usually less by
>such a small amount. Calling a virtual function the system has to fetch the
>virtual pointer which points to the virtual table. Then it fetch the
>address of the function. And finally call that function by address.
>
>It's not a big cost, but it is something. If your function does a lot of
>stuff then the time in the virtual function overhead is negligible by
>comparison. Say the overhead (of finding the virtual pointer, function,
>calling by address) is 100 nanoseconds. But the cost in the function to do
>everything else is 100,000 nanoseconds then the overhead is negligible.


The ideas are right, the numbers wrong by a loooong shot:

Let's take a 1 GHz Pentium or Athlon for numerical simplicity.
We've got 1 Billion cycles per second. If one instruction per second
was executed, we'd have 1 (ONE) nanosecond per instruction, rather
than 100. Now, typical latency is about 5 nanoseconds for an 'average'
instruction, but instruction processing rate is about 50 to 100 times
faster, due to 5 wide/20 deep pipelining for pentium, or 9 wide, 12
deep for AMD, which means a maximum of 100 instructions in flight at
any one time, which means about 50 on average (due to mispredictions,
etc.)

Still, that's about 0.1 (ONE TENTH) of a nano-second per instruction.

The cost of an indirection isn't much per se (not much more than
incrementing an integer). The real cost of indirection is **cache
misses**, which happens to be the biggest perfomance bottleneck in
real life applications. Too much data. Too little cache. If the CPU
has to go to L2 cache, that's many times slower than L1. If it has to
go to DRAM, the latency there is about 1/2 a microsecond, just to read
a stupid address. 1/2 a microsecond is the time the CPU could have
executed 5000 instructions, and instead had to twiddle thumbs waiting
for the data from DRAM to come in.

Of course, if you're USING that class's virtual table all the time,
chances are it will be in L1 cache when you need it. But that's if the
program is small and single-threaded. A large program with many
threads, where at every context switch the thread that comes in needs
full cache, causing the retiring of all cashed data for the previous
thread, you get much less cache efficiency.

Generally speaking, if you're concerned at all with performance, you
try to reduce and optimize data structures; you try to never keep
duplicate data, you try to use unsigned char rather than int for small
numbers, you try to use the most size-efficient containers possible,
and to increase locality as much as possible. And vtables are real
pain to put up with; specially when they are repeated on several
object files, and not to speak of classes fattened up by multiple and
virtual inheritance.

That's the REAL cost of vtables: non-locality of access, and cache
pollution; not to mention that the speculative execution unit can't
work (speculate) across jump tables, such that coming across any table
or switch statement will flush and starve the instruction pipelines...
(a cost overhead of about 50 instructions --highway toll).

Rolf Magnus

unread,
Sep 1, 2002, 8:37:14 AM9/1/02
to
chuck starchaser wrote:

> Now, typical latency is about 5 nanoseconds for an 'average'
> instruction, but instruction processing rate is about 50 to 100 times
> faster, due to 5 wide/20 deep pipelining for pentium, or 9 wide, 12
> deep for AMD, which means a maximum of 100 instructions in flight at
> any one time, which means about 50 on average (due to mispredictions,
> etc.)

I think that is very optimistic.

> The cost of an indirection isn't much per se (not much more than
> incrementing an integer). The real cost of indirection is **cache
> misses**, which happens to be the biggest perfomance bottleneck in
> real life applications.

Definitely.

> Too much data. Too little cache. If the CPU
> has to go to L2 cache, that's many times slower than L1. If it has to
> go to DRAM, the latency there is about 1/2 a microsecond, just to read
> a stupid address. 1/2 a microsecond is the time the CPU could have
> executed 5000 instructions, and instead had to twiddle thumbs waiting
> for the data from DRAM to come in.

The problem about that is that it's quite hard to find out how big the
performance hit of something is. Maybe there is almost no difference, maybe
you just stay under some unholy limits without using it, and it gets a lot
faster. Funny enough, this differs for different CPUs.

chuck starchaser

unread,
Sep 1, 2002, 9:51:50 AM9/1/02
to
On Sun, 01 Sep 2002 14:37:14 +0200, Rolf Magnus <rama...@t-online.de>
wrote:

>chuck starchaser wrote:
>
>> Now, typical latency is about 5 nanoseconds for an 'average'
>> instruction, but instruction processing rate is about 50 to 100 times
>> faster, due to 5 wide/20 deep pipelining for pentium, or 9 wide, 12
>> deep for AMD, which means a maximum of 100 instructions in flight at
>> any one time, which means about 50 on average (due to mispredictions,
>> etc.)
>
>I think that is very optimistic.


It is and it isn't: Consider a well designed and optimized app like
Quake, processing over a 1/4 million vertexes per second (1 division,
11 multiplications, and 20 or so add/sub's per vertex), plus managing
basic visibility, BSP, user interaction, network packets, openGL
calls, physics, collisions, AI.... The CPU AND GPU are so well
utilized you can fry your eggs on them.

Now compare that to Corel Draw, where, to load a 2D image with just a
few hundred straight lines, it takes 20 seconds to 2 minutes to show
it on the screen.

What happened here?

The difference a programmer can make to the performance of an
application is mind-boggling-ly ABYSMAL!!!!

It seems to me ridiculous how many people, even in this newsgroup,
keep throwing around the latest religion that says "trust the
compiler; the compiler can do better than you; don't think at the low
level".

That's absurd!


>The problem about that is that it's quite hard to find out how big the
>performance hit of something is. Maybe there is almost no difference, maybe
>you just stay under some unholy limits without using it, and it gets a lot
>faster. Funny enough, this differs for different CPUs.


That's it. The way to go is study, experiment and PROFILING. No sense
in further optimizing geometry if the problem is fill-rate. No sense
worrying about virtual tables if the video-card is choking. But I have
no profiler, and no money to buy one, so I'll just swear by inline
assembly and stay away from virtual/multiple/concrete inheritance, for
as long as I can, anyhow. God gave us templates, let's use them.

Magnus Lidbom

unread,
Sep 1, 2002, 10:25:58 AM9/1/02
to
> The difference a programmer can make to the performance of an
> application is mind-boggling-ly ABYSMAL!!!!
>
> It seems to me ridiculous how many people, even in this newsgroup,
> keep throwing around the latest religion that says "trust the
> compiler; the compiler can do better than you; don't think at the low
> level".
>
> That's absurd!

<snip>

>That's it. The way to go is study, experiment and PROFILING. No sense
>in further optimizing geometry if the problem is fill-rate. No sense
>worrying about virtual tables if the video-card is choking. But I have
>no profiler, and no money to buy one, so I'll just swear by inline
>assembly and stay away from virtual/multiple/concrete inheritance, for
>as long as I can, anyhow. God gave us templates, let's use them.

This may be true for apps like quake etc. For most applications however
a clean maintainable design is orders of magnitude more important than low
level optimizations. For the great majority of applications disregarding a
clean and logical design, and going with low level optimizations instead is
what's absurd.

I may have missed something but I don't believe this thread is about 3D games.

Regards /Magnus

Ioannis Vranos

unread,
Sep 1, 2002, 10:44:24 AM9/1/02
to
"Neil Butterworth" <neil_but...@lineone.net> wrote in message
news:3d716...@mk-nntp-1.news.uk.worldonline.com...

>
> Better still, notice his original question:
>
> "What is the cost of using virtual inheritance of a base class that
is
> abstract?"

You are right.


> I realise you don't know too much about C++, but you can read?


Now that is an insult attempt. Naturally it will be garbage collected.

> Does the
> phrase "virtual inheritance" in the question possibly suggest that
the OP is
> asking about ... virtual inheritance?


Is there even the notion of virtual inheritance cost? A virtual base
is unique for all derived classes in multiple inheritance (no
difference with non-virtual inheritance in simple inheritance case).

Ioannis Vranos

unread,
Sep 1, 2002, 10:48:44 AM9/1/02
to
"chuck starchaser" <chuck_st...@mail.com> wrote in message
news:trr3nukie4tda8ku3...@4ax.com...
>
>[...]

> Generally speaking, if you're concerned at all with performance, you
> try to reduce and optimize data structures; you try to never keep
> duplicate data, you try to use unsigned char rather than int for
small
> numbers, you try to use the most size-efficient containers possible,
> and to increase locality as much as possible. And vtables are real
> pain to put up with; specially when they are repeated on several
> object files, and not to speak of classes fattened up by multiple
and
> virtual inheritance.
> [...]

In the case your program is under severe time constraints you should
use templates and not virtual interfaces (or a mix of them).

chuck starchaser

unread,
Sep 1, 2002, 11:16:19 AM9/1/02
to
On Sun, 01 Sep 2002 14:25:58 GMT, "Magnus Lidbom"
<magnus...@hotmail.com> wrote:

>> The difference a programmer can make to the performance of an
>> application is mind-boggling-ly ABYSMAL!!!!
>>
>> It seems to me ridiculous how many people, even in this newsgroup,
>> keep throwing around the latest religion that says "trust the
>> compiler; the compiler can do better than you; don't think at the low
>> level".
>>
>> That's absurd!
>
><snip>
>
>>That's it. The way to go is study, experiment and PROFILING. No sense
>>in further optimizing geometry if the problem is fill-rate. No sense
>>worrying about virtual tables if the video-card is choking. But I have
>>no profiler, and no money to buy one, so I'll just swear by inline
>>assembly and stay away from virtual/multiple/concrete inheritance, for
>>as long as I can, anyhow. God gave us templates, let's use them.
>
>This may be true for apps like quake etc. For most applications however
>a clean maintainable design is orders of magnitude more important than low

Quake is clean and maintainable.
Many of the same techniques used for performance tuning are identical
to those being advocated for cleanliness, safety and maintainability.
Example:
I've been staying away from concrete class inheritance for performance
reasons, and I just bought the last book by Scott Meyers, and he
advocates no inheritance from concrete classes for safety reasons.
Acyclic graph organization of dependencies advocated for
maintainability makes perfect sense in terms of increasing locality of
data access.
Principles as old as structured programming: like don't keep copies of
the same information in different parts of the program, or they might
go out of synch. Makes perfect sense from the perspective of
performance: as well: The less data we keep around, the more the
chances are we'll find it in cache.

>level optimizations. For the great majority of applications disregarding a
>clean and logical design, and going with low level optimizations instead is
>what's absurd.

Equating concern with performance to disregard for design. That's
what's most absurd.

>I may have missed something but I don't believe this thread is about 3D games.

FYI: What I'm working on is not a game; it's a CAD system that's to
'live' in 3D, (as opposed to having a "3D view mode"). It shares a
lot with game applications in that A) it will use standard 3D video
card hardware acceleration, and B) in that I want it to be FAST,
instantaneous. I'm sick of CAD systems that keep growing in features
nobody wants, and slowing down in responsiveness.

Neither is this thread about GUI applications. It's about the C++
language. And what features of the language may or may not compromise
performance is PERFECTLY ON TOPIC. Not only that, it is still related
to the original question in this thread. So, if you don't care about
the issues being discussed in this particular thread, there's many
others for you.

Bye.


Magnus Lidbom

unread,
Sep 1, 2002, 11:59:59 AM9/1/02
to
> >>That's it. The way to go is study, experiment and PROFILING. No sense
> >>in further optimizing geometry if the problem is fill-rate. No sense
> >>worrying about virtual tables if the video-card is choking. But I have
> >>no profiler, and no money to buy one, so I'll just swear by inline
> >>assembly and stay away from virtual/multiple/concrete inheritance, for
> >>as long as I can, anyhow. God gave us templates, let's use them.
> >
> >This may be true for apps like quake etc. For most applications however
> >a clean maintainable design is orders of magnitude more important than low
>
> Quake is clean and maintainable.

I never meant to imply it wasn't, but I see now that what I said may well
be interpreted that way.

> Many of the same techniques used for performance tuning are identical
> to those being advocated for cleanliness, safety and maintainability.
> Example:
> I've been staying away from concrete class inheritance for performance
> reasons, and I just bought the last book by Scott Meyers, and he
> advocates no inheritance from concrete classes for safety reasons.
> Acyclic graph organization of dependencies advocated for
> maintainability makes perfect sense in terms of increasing locality of
> data access.
> Principles as old as structured programming: like don't keep copies of
> the same information in different parts of the program, or they might
> go out of synch. Makes perfect sense from the perspective of
> performance: as well: The less data we keep around, the more the
> chances are we'll find it in cache.

I'll admit I don't understand why inheriting from a concrete class would be
bad for performance. It sure is unsafe, but why slow? No polymorphism to
slow you down. Except for that part, that I don't get, I hear nothing here
that I'd consider low level. This is all pretty obvious.
What are we arguing about?


> >level optimizations. For the great majority of applications disregarding a
> >clean and logical design, and going with low level optimizations instead is
> >what's absurd.
>
> Equating concern with performance to disregard for design. That's
> what's most absurd.

I never said to disregard performance. I said that a clean and maintainable
design is orders of magnitude more important for most applications than
_low level_ optimizations. I meant stuff like using templates when inheritance
is the correct way to describe a model, char* instead of string, valarray
instead of vector, your own allocators that takes alignment into
consideration, cut n' paste instead of logical OO relationships, inline
assembly all over the place instead of in well isolated areas, platform
specific optimizations......


> Neither is this thread about GUI applications. It's about the C++
> language. And what features of the language may or may not compromise
> performance is PERFECTLY ON TOPIC.

I never said it wasn't on topic for this newsgroup.

> Not only that, it is still related
> to the original question in this thread. So, if you don't care about
> the issues being discussed in this particular thread, there's many
> others for you.

Basically you tell me to get lost because I said something you didn't agree
with Imho that type of attitude doesn't belong here.
Surely we can stay civil.

Best Regards /Magnus


chuck starchaser

unread,
Sep 1, 2002, 12:46:33 PM9/1/02
to
On Sun, 1 Sep 2002 17:48:44 +0300, "Ioannis Vranos"
<noi...@spammers.get.lost.hotmail.com> wrote:

>In the case your program is under severe time constraints you should
>use templates and not virtual interfaces (or a mix of them).

Exactly.

I do use polymorphism, but
1) only inherit non-virtually and from abstract classes
2) at high level.

After all, polymorphism was invented for polymorphically invoking
commands and services on objects, via references. Polymorphism was NOT
invented to control data conversion paths. Interfaces via references
are the business of inheritance and OO design. Data assignment,
conversion, comparison, and the so called 'binary operators' are
governed by data conversion compatibility rules that are COMPLETELY
orthogonal to interface compatibility, and are none of the business of
inheritance.
I'm convinced that mixing functions and data in the concept of class,
was a mistake; and I try to get around it by segregating my classes
between 'data types' and 'interfaces' or 'pimpl's. Datas I make
non-inheritable. Interfaces I make non-copy-able.
All my data types are ground-level, non-hyerarchical, and their data
conversion paths are coded as non-member operators and functions.
My interfaces usually inherit from abstract hyerarchies, have no
overloaded operators, no access to the data (impl) except through that
impl's own operators, and have segregated command and query member
functions.

But note that, in most applications, there's likely to be more 'data
types', whereas at the high level we'll be dealing more with
interfaces. So it agrees with the interest of perfomance: of using
polymorphism at the high level.

But I won't make RGB, RGBA, YUV, and YUVA classes derived from some
COLOR_FORMAT class, just for the sake of introducing virtual tables
where none is needed.

Yes, RGBA ***IS*** a COLOR_FORMAT... and so what? Every class is a
class, yet we don't derive them from an abstract class 'Class'.

At the low level I use templates, non-member operators, and even
C-style functions with return via pointer arguments, whatever it takes
to minimize overheads. And at the lowest level I go nuts with
MMX/3DNow! Still keeping an OO interface, but in the .cpp file, I
could show you, every function body begins with #asm{.

In

chuck starchaser

unread,
Sep 1, 2002, 12:54:36 PM9/1/02
to
On Sun, 1 Sep 2002 17:44:24 +0300, "Ioannis Vranos"
<noi...@spammers.get.lost.hotmail.com> wrote:

>"Neil Butterworth" <neil_but...@lineone.net> wrote in message
>news:3d716...@mk-nntp-1.news.uk.worldonline.com...
>>
>> Better still, notice his original question:
>>
>> "What is the cost of using virtual inheritance of a base class that
>is
>> abstract?"
>
>You are right.
>
>
>> I realise you don't know too much about C++, but you can read?
>
>
>Now that is an insult attempt. Naturally it will be garbage collected.
>
>
>
>> Does the
>> phrase "virtual inheritance" in the question possibly suggest that
>the OP is
>> asking about ... virtual inheritance?
>
>
>Is there even the notion of virtual inheritance cost? A virtual base
>is unique for all derived classes in multiple inheritance (no
>difference with non-virtual inheritance in simple inheritance case).


Actually, Ioannis, this may be just an issue with my compiler, but the
one time I tried using virtual inheritance, my derived classes would
grow fatter by 4 or 8 bytes, I can't remember which. (Never touched it
again, of course.. :-). Regular inheritance doesn't seem to incur
such cost.


Ioannis Vranos

unread,
Sep 1, 2002, 3:11:39 PM9/1/02
to
"chuck starchaser" <chuck_st...@mail.com> wrote in message
news:n6h4nugf596b5lrfp...@4ax.com...

>
> Actually, Ioannis, this may be just an issue with my compiler, but
the
> one time I tried using virtual inheritance, my derived classes would
> grow fatter by 4 or 8 bytes, I can't remember which. (Never touched
it
> again, of course.. :-). Regular inheritance doesn't seem to incur
> such cost.


Interestingly you are right! The code:


#include <iostream>


class A
{};

class B
{};

class C:virtual public A, virtual public B
{};


class D:virtual public A, virtual public B
{};


class E:public A, public B
{};

class F:public A, public B
{};


class G: public C, public D
{};

class H: public E, public F
{};


int main()
{
using namespace std;

cout<<"\nsizeof(G): "<<sizeof(G)<<endl;
cout<<"sizeof(H): "<<sizeof(H)<<endl;
}


produces:


GCC:

sizeof(G): 8
sizeof(H): 2


BC++:

sizeof(G): 32
sizeof(H): 32


Intel C++:

sizeof(G): 12
sizeof(H): 3

G is the virtual inheritance product.

Probably the compilers store much data. But i guess it doesn't impose
any time cost.

chuck starchaser

unread,
Sep 1, 2002, 3:46:32 PM9/1/02
to
On Sun, 01 Sep 2002 15:59:59 GMT, "Magnus Lidbom"
<magnus...@hotmail.com> wrote:

>Surely we can stay civil.

All right, let's cool it. But you did insinuate I was OT though.

I am NOT O.T.: Safety, Performance, Features, Expressiveness, these
are ALL valid aspects of the language to discuss. EQUALLY valid
aspects. You may be more concerned with portability; I may be more
concerned with issues of performance. But I never suggested that my
pet concerns were more important than yours, and you shouldn't suggest
that your pet concerns are more important than mine.

Without going too deep into Philosophy, the question of Value has
never been settled by a formal proof, but most scholars have agreed to
leave it to the market to decide. And in my experience, people don't
come to C++ primarily for the sake of portability, though it IS a very
heavy factor. They'd go for Java, if that were the case. And they
don't come to C++ for the sake of type-safety, either. They'd go for
Eiffel if that were the case. And they don't come to C++ for the sake
of Performance alone either, or else they'd use C or Fortran.
People flock to C++ because they get decent, respectable portions of
portability, type safety and performance, in the right ratios.

And you might say that the success of the STL was due to its
versatility compared to any libraries that preceeded it. And while I'd
agree this was a major, MAJOR factor, historically I remember that at
the time the STL came out, most programmers would praise its speed,
more than anything else.

>I'll admit I don't understand why inheriting from a concrete class would be
>bad for performance. It sure is unsafe, but why slow? No polymorphism to
>slow you down. Except for that part, that I don't get, I hear nothing here
>that I'd consider low level. This is all pretty obvious.
>What are we arguing about?

Granted, if you use polymorphism you'll have vtables no matter. The
link to performance is rather indirect: Most of the time, when I use
inheritance is to tag classes about possessing a qualifying attribute,
which may be extrinsic. So I may inherit some classes from an abstract
base just so that those classes, and no other classes, will fit the
type of a function parameter; not necessarily with the intent of
calling functions via a base pointer. In fact, the classes might be
otherwise un-related, and never override more than one function, and
might do so the same way.
Often I use abstract classes inheriting from other abstract classes,
sometimes multiply so, but in the end, I end up with a single concrete
class derived from them. I.e.: my abstract classes are there for the
sake of interface abstraction building, not polymorphism.

Now, if I inherited from a concrete class, it would be for the sake of
polymorphism. One might say, not necessarily, but it is, indirectly, a
necessary conclusion. Because inheritance would pose such high risks,
in terms of UNINTENDED polymorphism, or possible data conversion
snafus, that I would NEVER inherit from a concrete class, unless I
needed polimorphism as a matter of life or death, in the first place.

Now, if I have a single concrete class derived from one or more
abstract classes, and none of its functions are virtual, the compiler
should be able to figure out that the virtual table can be disposed
of, optimized away. There's only one class, what for have a table?
And if I have a bunch of classes simply 'tagged' by inheritance from a
base class with say a pure virtual destructor; and they share no other
functions, and override with only an empty destructor, all have the
same size, and are never called polymorphically, I should hope the
compiler would dispose of any virtual table it may have thought of.
But even if it does put a virtual table there, the fact that I don't
USE it, should be a performance advantage, in and of itself.
I hardly ever NEED polymorphism. Say RGBAcolor, and YUVAcolor, they
ARE color formats, for sure. Does that mean that they OUGHT to be
derived from a Color_Format class? Certainly that would be the easy
way. But it would be overkill; for I can set up things so as to have
the type of color format known at compile time, and use template
specialization. Sure, inheritance would look cleaner, but I'm
concerned more with performance, so I bunch polymorphism together with
RTTI, in the look but don't touch box.

And so, that's why I don't derive from concrete classes, and its
indirect relation to performance.


>_low level_ optimizations. I meant stuff like using templates when inheritance
>is the correct way to describe a model, char* instead of string, valarray

I think I've just made my pronouncement on 'correctness'.

char* instead of string... well, I'm going to dissapoint you: I do use
char* instead of std::string, but not for performance reasons, as much
as code-size. And because printf() is a lot easier and INTUITIVE to
use and format. I forced myself to use std::string, for a while, you
see. I hoped I'd get used to it, but never did. And I won't take flak
or shaming from you or from anybody about it. It is simply a fact: the
interface of std::string is simply ***AWFUL***. Garbage!

And it won't be long before the world realizes that the emperor had no
clothes on. And then they might wake up to the fact that fopen() won't
take a string for an argument. That mem_fun will work with a vector of
pointers, but not with a vector of std::auto_ptr<>'s....

Which, by the way, you try and pass an auto_ptr to a function. So, we
haven't gained in over-all safety, with auto_ptr, we've covered one
set of un-safeties and opened ourselves up to a new set of
un-safeties... Before we risked memory leaks; now we risk objects
evaporating...

And I love the STL, don't get me wrong. But error messages have gotten
so un-scrutable and long, we might as well turn off error reporting
and debug 'by ear'.

>instead of vector, your own allocators that takes alignment into
>consideration, cut n' paste instead of logical OO relationships, inline

The STL takes alignment into careful consideration. Why shouldn't I?

>assembly all over the place instead of in well isolated areas, platform

My assembly is restricted to the local scope of functions... :)

No, but seriously. I want to clarify a myth here: It took me years of
thinking about it, and finally took the plunge and started writing
assembly. Well, you'll be surprised: The same size and type of routine
that would take me 10 or 20 re-compiles to clean up typos and syntax
and forgotten *'s or &'s, I sometimes get to compile, AND test okay,
on the first try, when I write it in Assembler. It makes me wonder if
abstraction is not for the birds, or something.

>specific optimizations......

The best and juciest and most tantalizing optimizations are usually
platform-specific. Will you refrain from using threads just because
they are different in Win32 and POSIX?
Would you refrain from a 10x speed-up in video performance you could
get by using NVidia and/or ATI's shaders in vendor-specific language?

Now, of course I want portability. But right now I'm living in win32,
so I'll use win32 threads. When the time comes to port my CAD system
to Linux, I'll figure out pthreads, or ask for help.

Is this approach so sinful?

Do you refrain from using libraries, ALTOGETHER, just because they are
platform specific? Maybe you do. Like I said, my priorities are
different from yours, and I have no idea what your project might be,
but if you say performance is not an issue, fine with me. Just don't
attack me for being more concerned with performance than with the
political 'correctness' of std::string.

(A note on the side: I know there's exception and thread-safety issues
concerning stdio. I just don't care, because my app doesn't use text
strings anyways, except for debugging purposes. And by the time it
does come to need strings for UI, by then I plan to have an embedded
Python interpreter handling the UI anyways.)


chuck starchaser

unread,
Sep 1, 2002, 5:14:40 PM9/1/02
to
On Sun, 1 Sep 2002 22:11:39 +0300, "Ioannis Vranos"
<noi...@spammers.get.lost.hotmail.com> wrote:

>
>Probably the compilers store much data. But i guess it doesn't impose
>any time cost.


Haven't got a profiler; but I just don't trust virtual inheritance.
Space IS Money.. I mean Time.
If I'm careful to keep my classes with their members sorted in
descending order by size, and try so hard to get the final sizes to be
at or close below a power of two, to improve cache utilization and
memory bus bandwidth, the last thing I'm ready to accept is the
compiler screwing it all up for me... >:-0

Neil Butterworth

unread,
Sep 1, 2002, 5:27:32 PM9/1/02
to

"chuck starchaser" <chuck_st...@mail.com> wrote in message
news:vf05nugn9k48mn3h3...@4ax.com...

This obviously depends on your application domain. For what I do (multi-tier
servers in the finance industry) the bottlenecks are network and database
performance - my C++ applications are at least 3 orders of magnitude faster
than these limiting constraints, so worrying about class size is, for me,
somewhat unproductive.

NeilB


Ioannis Vranos

unread,
Sep 1, 2002, 7:31:09 PM9/1/02
to
"chuck starchaser" <chuck_st...@mail.com> wrote in message
news:vf05nugn9k48mn3h3...@4ax.com...


Well it depends on what we want. Programming involves trade offs. If
you have to program for a usual Windows machine you have not 8-byte
time constraints. On the other hand if you have severe space
constraints (you program for a wrist watch or something) you will use
naturally optimised messy code. There is not one approach right for
all purposes (even in the same paradigm). For regular PC applications
where there is a need for the notion of a common virtual base (for
example all dog kinds cannot have more than one head) 8 bytes
additional space cost will not cause any problem.

I have the sense that we all the old computer users have this space
efficiency stress and will have it in whole our life (but this is a
philosophical subject).


Do you remember memmaker?

chuck starchaser

unread,
Sep 1, 2002, 9:50:09 PM9/1/02
to
On Mon, 2 Sep 2002 02:31:09 +0300, "Ioannis Vranos"
<noi...@spammers.get.lost.hotmail.com> wrote:

>Well it depends on what we want. Programming involves trade offs. If
>you have to program for a usual Windows machine you have not 8-byte
>time constraints. On the other hand if you have severe space
>constraints (you program for a wrist watch or something) you will use
>naturally optimised messy code. There is not one approach right for

assert( Optimized != "Pessimized");
Optimizations often force me into better organization and
documentation.
In my day job I work with 8 bit microcontrollers. I use Assembler, and
my programs are always clear and easy to maintain. My colleagues swear
by embedded C cross-compilers. Their code is often inscrutable.
Last month I had to do a project using the C compiler for PIC
microcontrollers; I couldn't hold it from degenerating into an
inscrutable mess. Same thing programming my Duron box: When I'm
working in C++ it takes me countless compiles to get all the typos and
confusions out of the code. If I write the same code in assembler, it
usually compiles and tests okay on first or second compile.
Abstraction has a mesmerizing charm that's way out of proportion with
its real benefits.
You know what's the most powerful feature of C++, in my opinion? Its
IDIOMS. Never mind inhertance, polymorphism. Idioms, like pimpl_,
state, visitor, singleton, traits, etc. We're in the process of coming
up with a new and better language, whether we know it or not; just
like C programmers were slowly inventing C++ without knowing it, when
they started grouping related data at file (static) scope, and export
functions to modereate access to it.

>all purposes (even in the same paradigm). For regular PC applications
>where there is a need for the notion of a common virtual base (for
>example all dog kinds cannot have more than one head) 8 bytes
>additional space cost will not cause any problem.

Dogs usually have only one head. I agree.
But does that need to be expressed via some class hyerarchy? That's
the crucial question: What do you NEED in terms of hyerarchies to get
the job done? For if you want the type of language whereby you make
declarative statements, rules, etceteras, describing every conceivable
detail, until its knowledge base knows enough to even guess what your
question was in the first place, there's declarative languages,
functional languages, and a number of AI projects, to that end.
In C++ you don't just model all possible 'is-a' relationships
through class hyerarchies "just in case it might be useful". You try
to code the minimum possible.
As I said before, RGB_color and YUV_color should conform to
PIXEL_FORMAT via inheritance, if we were trying to model a real world
'is a' relationship. However, it has no USEFULNESS to do so, and would
introduce a virtual table de-reference every time I'd write a pixel !
And on top of that, PIXEL_FORMAT would become ASSIGNABLE from
RGB_color, which probably wasn't the idea anyhow.

>I have the sense that we all the old computer users have this space
>efficiency stress and will have it in whole our life (but this is a
>philosophical subject).

More than philosophical. Maybe we should all go back to 640K for a
while... just for the exercise. We should have listened to Bill Gates.

>Do you remember memmaker?
DO I EVER! Took 3 reboots, but allways got the job done. Magical
numbers were not so deprecated back then :)... those real mode
addresses it came up with...

Steve Heller

unread,
Sep 2, 2002, 12:40:56 AM9/2/02
to
chuck starchaser <chuck_st...@mail.com> wrote:

>My interfaces usually inherit from abstract hyerarchies,

I hate to be pedantic, but is there a reason you continually misspell
"hierarchy" and related words? I find it distracting when trying to
read your messages.

--
Steve Heller
http://www.steveheller.com
Author of "C++: A Dialog", "Optimizing C++", and other books
Free online versions of "Who's Afraid of C++?" and "Optimizing C++" are now available
at http://www.steveheller.com/whos and http://www.steveheller.com/opt

Bart.Van...@nowhere.be

unread,
Sep 2, 2002, 5:31:43 AM9/2/02
to
chuck starchaser <chuck_st...@mail.com> wrote:
> Principles as old as structured programming: like don't keep copies of
> the same information in different parts of the program, or they might
> go out of synch. Makes perfect sense from the perspective of
> performance: as well: The less data we keep around, the more the
> chances are we'll find it in cache.

Not necessarily. A copy in the padding space of another object you load
anyway is better than loading two objects seperatly.

cu bart

--
http://www.irule.be/bvh/

Ioannis Vranos

unread,
Sep 2, 2002, 7:41:24 AM9/2/02
to
"chuck starchaser" <chuck_st...@mail.com> wrote in message
news:66d5nu4ogg3ccibhb...@4ax.com...

>
> assert( Optimized != "Pessimized");
> Optimizations often force me into better organization and
> documentation.
> In my day job I work with 8 bit microcontrollers. I use Assembler,
and
> my programs are always clear and easy to maintain.


You are probably Neo of Matrix. :)

> My colleagues swear
> by embedded C cross-compilers. Their code is often inscrutable.
> Last month I had to do a project using the C compiler for PIC
> microcontrollers; I couldn't hold it from degenerating into an
> inscrutable mess. Same thing programming my Duron box: When I'm
> working in C++ it takes me countless compiles to get all the typos
and
> confusions out of the code. If I write the same code in assembler,
it
> usually compiles and tests okay on first or second compile.
> Abstraction has a mesmerizing charm that's way out of proportion
with
> its real benefits.

Well in your microcontroller programming life, naturally abstract
interfaces and probably virtual bases have not a place.

> You know what's the most powerful feature of C++, in my opinion? Its
> IDIOMS. Never mind inhertance, polymorphism. Idioms, like pimpl_,
> state, visitor, singleton, traits, etc. We're in the process of
coming
> up with a new and better language, whether we know it or not; just
> like C programmers were slowly inventing C++ without knowing it,
when
> they started grouping related data at file (static) scope, and
export
> functions to modereate access to it.


Yes. C++ is *very* wise. I guess it is natural since Stroustrup is
very wise too.

> Dogs usually have only one head. I agree.


Also Dogs have nothing to do with microcontroller applications. So why
you do not use virtual bases in that area is understandable. But
everything is not microcontrollers so i can afford virtual bases with
8 bytes space cost in my PIII 1 GHZ/1GB RAM PC.

> But does that need to be expressed via some class hyerarchy? That's
> the crucial question: What do you NEED in terms of hyerarchies to
get
> the job done?


If it is feasible, everything should be done as small, efficient
concrete type. If the notion of an abstract hierarchy with virtual
bases makes the problem easily comprehensible and you have not severe
space/time constraints, we should do it that way.

> In C++ you don't just model all possible 'is-a' relationships
> through class hyerarchies "just in case it might be useful". You try
> to code the minimum possible.

Yes. Concrete types should be preferred wherever convenient. If the
notional convenience is an hierarchy, we should make an hierarchy (for
example in a graphic library of animals).

> As I said before, RGB_color and YUV_color should conform to
> PIXEL_FORMAT via inheritance, if we were trying to model a real
world
> 'is a' relationship. However, it has no USEFULNESS to do so, and
would
> introduce a virtual table de-reference every time I'd write a pixel
!
> And on top of that, PIXEL_FORMAT would become ASSIGNABLE from
> RGB_color, which probably wasn't the idea anyhow.


You are always thinking low level. :) For the above i would use
concrete types. If i was severely constrained i would use enumerations
& variables in a namespace (and some simple structs if possible).


> More than philosophical. Maybe we should all go back to 640K for a
> while... just for the exercise. We should have listened to Bill
Gates.


:)) BillG has said that he never said that and that is a hoax.


On the other hand, nothing can stop evolution. This space/time syndrom
we the old users have (my first PC was a 10 MHz XT with CGA/Hercules)
doesn't apply for the Windows generation. As the horsepower increases
and the space increases too, the abstraction will be increasing.
Consider the new .NET which is magnificent in many ways.


But C++ must keep the spirit of maximum space/time efficiency while
adding abstractions (the spirit that if you did the same thing in C90
the resulting code would not be faster or larger). For example in
virtual functions case, if you did the housekeeping yourself (stored
type identification) the resulting code would not be smaller or faster
(but usually larger and slower).


> >Do you remember memmaker?

> DO I EVER! Took 3 reboots, but allways got the job done. Magical
> numbers were not so deprecated back then :)... those real mode
> addresses it came up with...


Yes it was around the same time that there were the slogans (at least
here in Greece) "real men do it on keyboard only", "DOS never dies".
Especially for DOS, when i saw the new Dosshell i thought that indeed
DOS would never die.

chuck starchaser

unread,
Sep 2, 2002, 8:32:23 AM9/2/02
to

In terms of access to cache absolutely. But as for loading into cache,
with AMD it is, with INTEL isn't. AMD's loading of a (32-byte) cache
line begins at the actual address you request, then wraps around. With
P4's, loading of the (64-byte) cache lines always begins at the lowest
address; so if your object is in the padding space of another, and
towards the end of a cache line, it may take a long time to load from
system memory.
But the benefits of more efficient use of the cache probably far
outweight loading latency costs.

chuck starchaser

unread,
Sep 2, 2002, 8:35:36 AM9/2/02
to
On Mon, 02 Sep 2002 04:40:56 GMT, Steve Heller <st...@steveheller.com>
wrote:

>chuck starchaser <chuck_st...@mail.com> wrote:
>
>>My interfaces usually inherit from abstract hyerarchies,
>
>I hate to be pedantic, but is there a reason you continually misspell
>"hierarchy" and related words? I find it distracting when trying to
>read your messages.

Sorry, English is my second language. I'll be sure to remember
"hierarchy". Please let me know if I mishpel anything else :-)

Steve Heller

unread,
Sep 7, 2002, 6:57:50 PM9/7/02
to
chuck starchaser <chuck_st...@mail.com> wrote:

I'll be glad to. By the way, your English is so good in general that I
couldn't tell it wasn't your first language. Thanks for your
contributions to the group!

0 new messages