Re: vtable with virtual base class?
Thanks for the response and it answered exactly what I was looking
for. I agree that the penalty is small and "worth paying" to avoid the
duplicated code, when it's REALLY necessary and there's not a better
design to handle the problem.
Also, just for anyone else who may stumble along this thread. I found
this article ( http://www-plan.cs.colorado.edu/diwan/class-papers/mi.pdf
) and Section 7 actually discusses the logic behind the use of virtual
base classes to resolve the "diamond problem" and Section 7.1
discusses the methodology used to implement the virtual base classes
in multiple inheritance (which is the method that James had pointed
out). Also, I didn't even think about this, but it points outs that
"one can cast from a derived class to a virtual base class, but not
from a virtual base class to a derived class" and it explains the
reasoning as to why.
Thanks again for the help and the quick response,
Dave
On Dec 11, 2:36 am, James Kanze <james.ka...@gmail.com> wrote:
On Dec 11, 5:56 am, Dave Johansen <davejohan...@gmail.com> wrote:
I've done some searching and haven't been able to an answer to
this question, but is a vtable (or any other sort of overhead)
created/ added with using virtual inheritance to resolve the
"diamond problem" when there are no virtual functions?
For example, let's say that I have a setup like this
class base_data
{
static const int NUM_VALUES = 5;
...
protected:
int m_data[NUM_VALUES];
};
class data_reader : public virtual base_data
{
...
public:
data_reader &operator>>(int &value)
{
value = data[m_index];
m_index = (m_index + 1) % NUM_VALUES;
return *this;
}
...
protected:
int m_index;
};
class data_writer : public virtual base_data
{
...
public:
data_writer &operator<<(int value);
{
data[m_index] = value;
m_index = (m_index + 1) % NUM_VALUES;
return *this;
}
...
protected:
int m_index;
}
class data_reader_and_writer : public data_reader, public data_writer
{
...
};
I realize that the virtual inheritance used with data_reader/
data_writer allows data_reader_and_writer to have only a
single instance of the base_data class that is shared so the
reading and writing will happen from the same array (I realize
that the read and write indexes will be disjoint/independent
in this implementation), but is there anything else that's
different about data_reader, data_writer, or
data_reader_and_writer (other than the single instance of
base_data, of course)? Anything else added to them? Or any
sort of performance penalty?
It depends on what you call a penalty. In a typical
implementation, each class will be laid out without considering
the virtual bases, then the virtual bases will be tacked onto
the end of the most derived class. So, for example, in your
case, if you have a data_reader object or a data_writer object,
it will be laid out:
data_reader::m_index
base_data::m_data
or
data_writer::m_index
base_data::m_data
, and a data_reader_and_writer will be laid out:
data_reader::m_index
data_writer::m_index
base_data::m_data
Note that the position of base_data::m_data in data_reader
varies depending on what the most derived class is. Which isn't
known to data_reader. The compiler must thus generate extra
code or data to find it dynamically: this may take the form of
an extra hidden pointer (in addition to the vptr) in the class
(which is initialized by the most derived class), or an
additional entry in the vtable, with the offset of the base
class. (Presumably, other implementations are also possible,
but these are the two I know of.)
Does this result in a "penalty"? Compared to what: if you don't
actually need virtual inheritance, then using it does have an
additional cost, although in most cases, it's probably
negligible. If you need it, I'd guess that most of the time,
the additional cost is less than the cost of the alternatives.
--
James Kanze (GABI Software) email:james.ka...@gma=
il.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Dat=
enverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34