POV-Ray : Newsgroups : povray.programming : C++ problem : Re: C++ problem Server Time
28 Jul 2024 14:34:45 EDT (-0400)
  Re: C++ problem  
From: Warp
Date: 29 Jul 2001 07:20:50
Message: <3b63f192@news.povray.org>
In povray.programming Thorsten Froehlich <tho### [at] trfde> wrote:
: Yes, and one that isn't very well explained anywhere but in the source code
: of compilers :-(

  You might already know what virtual inheritance does, but let me explain it
anyways in case anyone is interested (which I doubt, but for some reason I
like to write these kind of things... :) ).

  Virtual inheritance (class B: virtual public A) by itself doesn't do
anything, and it has effect exclusively when using the so-called "diamond
inheritance", that is, when making multiple inheritance from classes with a
common base class. Any other use of virtual inheritance has no effect.

  The idea is the following:

  Suppose that you have a class like this:

class A
{
 public:
    void modify_x();

 private:
    int x;
};

  Now we make regular inheritance to create the classes B and C:

class B: public A { public: void f(); ... };
class C: public A { public: void g(); ... };

  Both will have their own "copy" of A, that is, in practice their own
copy of the "x" variable. That is, the structure of the B class will be
like this (ascii-art follows):

B:
,----------------------,
| A-part : int x       |
|----------------------|
| B-part : B variables |
`----------------------'

  The C class will be similar. Also suppose that the f() function in B
calls modify_x() to modify the x variable inside B and similarly the g()
function calls modify_x() to modify the x variable inside C.

  Now if we make a class D which is inherited from both B and C, ie:

class D: public B, public C { ... }

the structure of D will look like this:

D:
,----------------------,
| A-part : int x       |
|----------------------|
| B-part : B variables |
|----------------------|
| A-part : int x       |
|----------------------|
| C-part : C variables |
|----------------------|
| D-part : D variables |
`----------------------'

  The x variable will appear twice in the class, once for B and once for C.
If we call f(), it will modify (through modify_x()) the first x, and if we
call g(), it will modify the second x. Modifying one will not affect the
other.

  Sometimes this is exactly the behaviour one wants. This is usually so if
D is not interested in the x variable, but it's used exclusively for internal
calculations of B and C.
  However, sometimes this is not what one wants, specially if D is interested
in x. In this case one would want the x variable to appear just once in D and
both f() and g() should modify the same x.
  This is where virtual inheritance kicks in. It's used specifically for this
purpose. It works like this:

  If we know that a "diamond inheritance" will be used for B and C and that the
variables of A should appear only once in the final class, they have to be
inherited virtually, that is:

class B: virtual public A { public: void f(); ... };
class C: virtual public A { public: void g(); ... };

  The class D is inherited from B and C in the regular way (ie. it doesn't need
to be inherited virtually).
  After this modification D will look like this:

D:
,----------------------,
| A-part : int x       |
|----------------------|
| B-part : B variables |
|----------------------|
| C-part : C variables |
|----------------------|
| D-part : D variables |
`----------------------'

  Now both f() and g() will modify the same x variable instead of having an own
copy of it.

  This might look simple, but if one begins to think about how this can be
implemented at low-level, one will soon realize that it's far from simple.
  This is because when f() is called, the function f() sees only the "B-part"
of the class, nothing else (in practice 'this' will point to the beginning of
"B-part" instead of the beginning of the whole D class). Thus it can't directly
know where x is located (because it's no longer located in the B-part but
somewhere else). Similarly the g() function, which should modify the same x,
can't know its location directly because it's not inside the C-part either.


-- 
#macro N(D,I)#if(I<6)cylinder{M()#local D[I]=div(D[I],104);M().5,2pigment{
rgb M()}}N(D,(D[I]>99?I:I+1))#end#end#macro M()<mod(D[I],13)-6,mod(div(D[I
],13),8)-3,10>#end blob{N(array[6]{11117333955,
7382340,3358,3900569407,970,4254934330},0)}//                     - Warp -


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.