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

private inheritance vs containment

6 views
Skip to first unread message

Sam

unread,
May 27, 2007, 9:27:17 PM5/27/07
to
I know that this one has been discused many times and every single book
about C++ advices to first consider containment.

But I feel that there is a legitimate use of private inheritance when a
single condition is met (the base class has no virtual functions, so
inheriting from your class will not have a customization point you don't
intent to give) and the (small) extra performance private inheritance
gives is needed.

Any comments on my thinking.

Thanks in advance.

Sam.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Seungbeom Kim

unread,
May 28, 2007, 9:29:03 AM5/28/07
to
Sam wrote:
> I know that this one has been discused many times and every single book
> about C++ advices to first consider containment.
>
> But I feel that there is a legitimate use of private inheritance when a
> single condition is met (the base class has no virtual functions, so
> inheriting from your class will not have a customization point you don't
> intent to give) and the (small) extra performance private inheritance
> gives is needed.

As a general advice, you may want to check out this C++ FAQ Lite topic:
[24] Inheritance - private and protected inheritance
http://www.parashift.com/c++-faq-lite/private-inheritance.html

and this message and thread from the past for a particular situation
where private inheritance is very useful:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/35c34091a34298f8/f4b765eb77950dfa#f4b765eb77950dfa

However, I cannot imagine a case where private inheritance will give
you any extra performance over containment. Can you give an example?

--
Seungbeom Kim

Daniel T.

unread,
May 28, 2007, 9:31:14 AM5/28/07
to
Sam <sak...@yahoo.com> wrote:

> I know that this one has been discused many times and every single book
> about C++ advices to first consider containment.
>
> But I feel that there is a legitimate use of private inheritance when a
> single condition is met (the base class has no virtual functions, so
> inheriting from your class will not have a customization point you don't
> intent to give) and the (small) extra performance private inheritance
> gives is needed.
>
> Any comments on my thinking.

Just the opposite is true. Consider:

class Foo {
public:
virtual void func();
};

class Bar : private Foo {
public:
virtual void func(); // override here
};

To do the same with containment would require an extra class:

class FooChild : public Foo {
public:
virtual void func(); // override here
};

class Bar {
FooChild foo;
};

Sam

unread,
May 28, 2007, 3:17:39 PM5/28/07
to
Seungbeom Kim wrote:
> Sam wrote:
>> ... and the (small) extra performance private inheritance
>> gives is needed.
>
> However, I cannot imagine a case where private inheritance will give
> you any extra performance over containment. Can you give an example?
>

When a contained object member function is called, its "this" pointer
must be calculated and passed to it. On the other hand in an inheritance
relationship the "this" pointer is the same with the derived object. No
calculation needed. Example:

struct A
{
void do_work();
};

// containment
class B
{
private:
A mA;
public:
void do_work() { mA.do_work(); }
}

// private inheritance
class C : private A
{
public:
void do_work() { A::do_work(); }
}

int main()
{
B b;

// gets address of b, calculates address of
// B::mA and calls A::do_work()
b.do_work();

C c;

// gets address of c, directlly calls A::do_work()
c.do_work();
}

Sam.

--

Daniel T.

unread,
May 28, 2007, 8:27:15 PM5/28/07
to
In article <f3erhm$fnq$1...@mouse.otenet.gr>, Sam <sak...@yahoo.com>
wrote:

> Seungbeom Kim wrote:
> > Sam wrote:
> >> ... and the (small) extra performance private inheritance
> >> gives is needed.
> >
> > However, I cannot imagine a case where private inheritance will give
> > you any extra performance over containment. Can you give an example?
> >
>
> When a contained object member function is called, its "this" pointer
> must be calculated and passed to it. On the other hand in an inheritance
> relationship the "this" pointer is the same with the derived object. No
> calculation needed.

The above is a micro-optimization that the compiler can likely take care
of itself.

> Example:
>
> struct A
> {
> void do_work();
> };
>
> // containment
> class B
> {
> private:
> A mA;
> public:
> void do_work() { mA.do_work(); }
> }
>
> // private inheritance
> class C : private A
> {
> public:
> void do_work() { A::do_work(); }
> }
>
> int main()
> {
> B b;
>
> // gets address of b, calculates address of
> // B::mA and calls A::do_work()
> b.do_work();
>
> C c;
>
> // gets address of c, directlly calls A::do_work()
> c.do_work();
> }

In the above code, the B::do_work function would likely be expanded
inline which means the "calculation" you speak of is done at compile
time, not run time. No performance advantage here.

Sam

unread,
May 28, 2007, 8:32:26 PM5/28/07
to
Daniel T. wrote:
> Sam <sak...@yahoo.com> wrote:
>
>> I know that this one has been discused many times and every single book
>> about C++ advices to first consider containment.
>>
>> But I feel that there is a legitimate use of private inheritance when a
>> single condition is met (the base class has no virtual functions, so
>> inheriting from your class will not have a customization point you don't
>> intent to give) and the (small) extra performance private inheritance
>> gives is needed.
>>
>> Any comments on my thinking.
>
> Just the opposite is true.
>

I don't really understand what your point is.
Can you elaborate please?

Sam.

Carl Barron

unread,
May 28, 2007, 10:48:09 PM5/28/07
to
In article <f3d8g6$o8l$1...@news.Stanford.EDU>, Seungbeom Kim
<musi...@bawi.org> wrote:

>
> However, I cannot imagine a case where private inheritance will give
> you any extra performance over containment. Can you give an example?

struct Private
{
void foo(){};
}

class A:private Private
{
public:
using Private::foo;
};

class B
{
Private b;
public:
void foo() {b.foo();}
};

A a;
B b;

b.foo() directly calls B::foo(), which calls Private::foo() but
a.foo() directly calls Private::foo(). Your compiler probably
will optimize the excess call away but private inheritance guarantees
the direct call of Private::foo().

Further private inheritance gives instant documentation that A uses
foo of Private with no changes. and using statements are ussually
shorter and less error prone than forwarding functions. Take your
pick.


--

ta0...@yahoo.com

unread,
May 29, 2007, 3:44:45 AM5/29/07
to
On May 27, 9:27 pm, Sam <saka...@yahoo.com> wrote:
> I know that this one has been discused many times and every single book
> about C++ advices to first consider containment.
>
> But I feel that there is a legitimate use of private inheritance when a
> single condition is met (the base class has no virtual functions, so
> inheriting from your class will not have a customization point you don't
> intent to give) and the (small) extra performance private inheritance
> gives is needed.

I use it in one of my template libraries. The basic idea is that the
class implements an abstract interface, but that interface cannot be
accessible externally or to derived classes; the class limits access
to that interface via a mutex. This ensures that the class itself can
cast to the abstract class under its own terms but nothing else can.
It's difficult to describe in a post, but here is the link.
http://capsule-ta0kira.sourceforge.net/
http://capsule-ta0kira.sourceforge.net/#IOS

Kevin P. Barry

Daniel T.

unread,
May 29, 2007, 3:40:37 AM5/29/07
to
Sam <sak...@yahoo.com> wrote:
> Daniel T. wrote:
> > Sam <sak...@yahoo.com> wrote:
> >
> > > I know that this one has been discused many times and every
> > > single book about C++ advices to first consider containment.
> > >
> > > But I feel that there is a legitimate use of private inheritance
> > > when a single condition is met (the base class has no virtual
> > > functions, so inheriting from your class will not have a
> > > customization point you don't intent to give) and the (small)
> > > extra performance private inheritance gives is needed.
> > >
> > > Any comments on my thinking.
> >
> > Just the opposite is true.
>
> I don't really understand what your point is. Can you elaborate
> please?

Maybe the FAQ will help:
http://www.parashift.com/c++-faq-lite/private-inheritance.html#faq-24.3

My point is that a legitimate use of private inheritance is when the
base class *does* have at least one virtual function, and you want to
override that function, but don't want the child class to be convertible
into the parent class.

Sam

unread,
May 29, 2007, 7:49:44 PM5/29/07
to
Daniel T. wrote:
> In article <f3erhm$fnq$1...@mouse.otenet.gr>, Sam <sak...@yahoo.com>
> wrote:
>
>> When a contained object member function is called, its "this" pointer
>> must be calculated and passed to it. On the other hand in an inheritance
>> relationship the "this" pointer is the same with the derived object. No
>> calculation needed.
>
> The above is a micro-optimization that the compiler can likely take care
> of itself.

Our perspective differ. You call it "micro-optimization", I call it "(small)
extra performance", others are concerned about the overhead of a virtual call
and others don't (virtual call's overhead compared to the containment overhead
is almost the same, fetch one extra address, the address of a function in the
first case, the address of the this pointer of the contained object in the
later).

>
>> Example:
>>
>> struct A
>> {
>> void do_work();
>> };
>>
>> // containment
>> class B
>> {
>> private:
>> A mA;
>> public:
>> void do_work() { mA.do_work(); }
>> }
>>
>> // private inheritance
>> class C : private A
>> {
>> public:
>> void do_work() { A::do_work(); }
>> }
>>
>> int main()
>> {
>> B b;
>>
>> // gets address of b, calculates address of
>> // B::mA and calls A::do_work()
>> b.do_work();
>>
>> C c;
>>
>> // gets address of c, directlly calls A::do_work()
>> c.do_work();
>> }
>
> In the above code, the B::do_work function would likely be expanded
> inline which means the "calculation" you speak of is done at compile
> time, not run time. No performance advantage here.
>

There are cases where the compiler can optimize the "calculation" / passing of
the this pointer, if for example

1. the address of the container object is the same with the contained object
2. the code of the A::do_work() function is known to the compiler not to use
any class member variables or methods so it doesn't need a this pointer
3. the called functions is known to access only class member variables that
can be calculated as offset from the address of the container object.

The above list of course is not exhaustive and is implementation dependent.
But private inheritance is not (implementation dependent).

Sam.

Sam

unread,
May 29, 2007, 7:50:14 PM5/29/07
to
Daniel T. wrote:
> Sam <sak...@yahoo.com> wrote:
>> Daniel T. wrote:
>>> Sam <sak...@yahoo.com> wrote:
>>>
>>>> But I feel that there is a legitimate use of private inheritance
>>>> when a single condition is met (the base class has no virtual
>>>> functions, so inheriting from your class will not have a
>>>> customization point you don't intent to give) and the (small)
>>>> extra performance private inheritance gives is needed.
>>>>
>>>> Any comments on my thinking.
>>> Just the opposite is true.
>> I don't really understand what your point is. Can you elaborate
>> please?
>
> Maybe the FAQ will help:
> http://www.parashift.com/c++-faq-lite/private-inheritance.html#faq-24.3
>
> My point is that a legitimate use of private inheritance is when the
> base class *does* have at least one virtual function, and you want to
> override that function, but don't want the child class to be convertible
> into the parent class.
>

I feel there is a misunderstanding going on here and after (re)reading my
original post it possibly is my fault.

Please change the words "But I feel that there is a legitimate use of private
inheritance" with "But I feel that there is **one more** legitimate use of
private inheritance".

Does this make a difference?

Sam.

Greg Herlihy

unread,
Jun 1, 2007, 9:53:04 AM6/1/07
to
On 5/29/07 4:49 PM, in article f3i6uv$pmu$1...@mouse.otenet.gr, "Sam"
<sak...@yahoo.com> wrote:

> Daniel T. wrote:
>> In article <f3erhm$fnq$1...@mouse.otenet.gr>, Sam <sak...@yahoo.com>
>> wrote:
>>
>>> When a contained object member function is called, its "this" pointer
>>> must be calculated and passed to it. On the other hand in an inheritance
>>> relationship the "this" pointer is the same with the derived object. No
>>> calculation needed.
>>
>> The above is a micro-optimization that the compiler can likely take care
>> of itself.
>
> Our perspective differ. You call it "micro-optimization", I call it "(small)
> extra performance", others are concerned about the overhead of a virtual call
> and others don't (virtual call's overhead compared to the containment overhead
> is almost the same, fetch one extra address, the address of a function in the
> first case, the address of the this pointer of the contained object in the
> later).

There is no "extra performance" obtained by using private inheritance
instead of containment in the example below - because the
"computational work" required by the semantics of either approach is
the same. In both cases, two methods are called and each is passed a
"this" pointer (at least conceptually) as a hidden argument. Since
neither of the "this" pointer arguments so passed is any more
expensive for the compiler to obtain than the other - and since
obtaining neither pointer requires any additional runtime information
over and above what is needed to obtain the other pointer - there is
no basis for concluding that private inheritance offers any
performance advantage (however minuscule) over containment.

In particular, any comparison between containment and virtual method
dispatching is simply erroneous. The compiler does not need b's
address in order to obtain b.mA's address. Because b.mA is located at
a known location within a B object (which in the code below happens to
be zero), the compiler can just as easily pass mA as a "this" pointer
argument as it can a pointer to b itself.

And real-world C++ compilers bear this observation out: on a typical
machine architecture, local variables are referenced as offsets
relative to a stack pointer. So, for example, if b is located at
0(SP), then mA would also be found at 0(SP) (in the example below) -
but even if mA were located 4(SP) or 8(SP) or wherever - there would
be no additional overhead incurred: instead of passing 0(SP) to each
of the two methods, the compiler would pass 0(SP) to the first method
and 4(SP) to the second and do so no less efficiently.

Compiled code is always "implementation-dependent." Eliminating a
second load instruction to pass the "this" argument to the second
method is just as much an optimization as optimizations #1-3 on the
list above. So when comparing the efficiencies of alternate
approaches, it only makes sense to assume an optimally efficient C++
compiler. Otherwise, if one is going to assume that the C++ compiler
does not produce optimally efficient code - then one cannot also
assume that the inefficiencies of the compiler-generated code (and
likewise, whatever optimizations the compiler did apply) will only
favor private inheritance. Yet that is exactly the argument that is
being made here: that the compiler will be smart enough to optimize
away a second load instruction for a this pointer argument when
calling the second method - but at the same time the compiler cannot
be smart enough to eliminate the load instructions completely because
they are not being used at all.

Greg

0 new messages