 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Keshav Guest
|
Posted: Mon Oct 17, 2005 1:59 pm Post subject: size of class having virtual functions |
|
|
Hi,
COde snippet is
class Base {
public:
virtual void ABC() {}
};
class Der1 : public Base {
public:
virtual void ABC() {}
};
class Der2 : public Base {
public:
virtual void ABC() {}
};
class Der3 : public Der1, public Der2 {
public:
virtual void ABC() {}
};
main() {
cout << sizeof(Der3) << sizeof(Der1) << sizeof (Base);
}
I would like to know why sizeof Der3 is 8? How is that might have
implemented?
Thanks
K2G
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze Guest
|
Posted: Tue Oct 18, 2005 10:22 am Post subject: Re: size of class having virtual functions |
|
|
Keshav wrote:
| Quote: | COde snippet is
class Base {
public:
virtual void ABC() {}
};
class Der1 : public Base {
public:
virtual void ABC() {}
};
class Der2 : public Base {
public:
virtual void ABC() {}
};
class Der3 : public Der1, public Der2 {
public:
virtual void ABC() {}
};
main() {
cout << sizeof(Der3) << sizeof(Der1) << sizeof (Base);
}
I would like to know why sizeof Der3 is 8? How is that might
have implemented?
|
Typically, there will be a vptr for each base hierarchy. If you
have an instance of Der3, you can point to it via a Der2* or a
Der1*. In the most general case, the vptr must be different for
these sub-objects. (One can easily imagine that Der1 and Der2
have different virtual functions.)
I'm not sure -- the empty base class optimization might apply
(but I hope not) -- but I think too that the two Base subobjects
must have different addresses as well.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
lulu yao Guest
|
Posted: Tue Oct 18, 2005 10:30 am Post subject: Re: size of class having virtual functions |
|
|
Der3 needs two vptrs, one for Der1, the other for Der2. 'cause you may
cast Der3 to any one of them, and they should work fine with old codes.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Tue Oct 18, 2005 10:36 am Post subject: Re: size of class having virtual functions |
|
|
This is one reason to avoid multiple inheritence unless you're
getting something from it that you couldn't get without it.
I'm going to add some data members, to make what's happening
easier to understand.
Keshav wrote:
| Quote: | Hi,
COde snippet is
class Base {
public:
virtual void ABC() {}
int bbb; // Added
};
|
Likely layout in memory:
(Assume pointers are 4 bytes each)
Offset 0: Virtual Pointer for class Base.
Offset 4: bbb
Total size is 8
| Quote: | class Der1 : public Base {
public:
virtual void ABC() {}
int ddd1; // Added
};
|
Likely layout in memory:
Offset 0: Virtual Pointer for class Der1/Base
Offset 4: bbb
Offset 8: ddd1
Total size is 12
If Der1 had any data items, they would start immediately
after the data items in Base (plus possible padding).
Note that we only need one virtual pointer. If we call a
virtual function in Base that was NOT overridden by Der1,
then that base function will still know how to access all
of the Base data items.
| Quote: | class Der2 : public Base {
public:
virtual void ABC() {}
int ddd2; // Added
};
|
Likely layout in memory:
Offset 0: Virtual Pointer for class Der2/Base
Offset 4: bbb
Offset 8: ddd2
Total size is 12
This shouldn't be surprising -- it's just like Der1.
| Quote: | class Der3 : public Der1, public Der2 {
public:
virtual void ABC() {}
int ddd3; // Added
};
|
Before you read how this is likely laid out, think about
how you would do it. Remember that you need to be able to
call virtual functions in EITHER instance of base, and
have the functions act correctly on that instance... that
means you're going to need more than one virtual pointer.
Here's how at least one compiler does it:
Offset 0: Virtual Pointer for class Der3/Der1/Base
Offset 4: bbb
Offset 8: ddd1
Offset 12: Virtual Pointer for class Der3/Der2/Base
Offset 16: bbb
Offset 20: ddd2
Offset 24: ddd3
Total size is 28
So we need more than one virtual pointer.
Now, remove members bbb, ddd1, ddd2 and ddd3 from my versions,
and you'll still end up with one virtual pointer in Base, Der1
and Der2... but you'll still have two virtual pointers in
Der3... so if pointers are 4 bytes, then Der3 will be size 8
and the rest will be size 4.
You could argue that since Base and Der1 had no data members,
the compiler could have used one virtual pointer for Der3...
but I doubt that there are very many compilers that can handle
that optimization, nor would it very often be important.
| Quote: | main() {
cout << sizeof(Der3) << sizeof(Der1) << sizeof (Base);
}
|
By the way, a nit -- you should always declare main()
to return an int. Function main() has always been allowed to
do this, even if it has no return statement... Many compilers
used to give a meaningless warning or error message if
int main() didn't return an int, but today many (most?)
compilers are smart enough to supress it, for function
main() only.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Tue Oct 18, 2005 10:36 am Post subject: Re: size of class having virtual functions |
|
|
Keshav <gupta.keshav (AT) gmail (DOT) com> wrote:
| Quote: | Hi,
COde snippet is
class Base {
public:
virtual void ABC() {}
};
class Der1 : public Base {
public:
virtual void ABC() {}
};
class Der2 : public Base {
public:
virtual void ABC() {}
};
class Der3 : public Der1, public Der2 {
public:
virtual void ABC() {}
};
main() {
cout << sizeof(Der3) << sizeof(Der1) << sizeof (Base);
}
I would like to know why sizeof Der3 is 8? How is that might have
implemented?
Thanks
K2G
As written this hierarchy is: |
Base Base
/
Der3
Der3 is contains two instances of Base one each for Der1 and Der2.
Each instance of Base has a vtable with a pointer to a function.
[apparently 4 bytes, total == 8]
if you want:
Base
/
Der1 Der2
/
Der3
then class Der1:virtual public Base{...};
class Der2:virtual public Base{...};
class DEr3:publuc Der1,public Der2{...};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter_Julian Guest
|
Posted: Wed Oct 19, 2005 8:48 am Post subject: Re: size of class having virtual functions |
|
|
"Keshav" <gupta.keshav (AT) gmail (DOT) com> wrote
| Quote: | Hi,
COde snippet is
class Base {
public:
virtual void ABC() {}
};
class Der1 : public Base {
public:
virtual void ABC() {}
};
class Der2 : public Base {
public:
virtual void ABC() {}
};
class Der3 : public Der1, public Der2 {
public:
virtual void ABC() {}
};
main() {
cout << sizeof(Der3) << sizeof(Der1) << sizeof (Base);
}
I would like to know why sizeof Der3 is 8? How is that might have
implemented?
Thanks
K2G
|
Yes, indeed, the fact that Der3 is 8 should ring some bells in the case
you needed a common base. Your inheritence hierarchy will suffer from
the "dreaded diamond" which you can read about here:
[25.8] What is the "dreaded diamond"?
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html
Both Der1 and Der2 should inherit virtually if you plan a common Base...
which then prompts me to insist you read the section about delegating to
sister classes as well. Only one path can manage a given behaviour of
that diamond.
Only one of the two mid classes should manage allocation of that
precious common base as well. As you can see below, access specifiers
are employed to resolve any ambiguity. This is specially critical should
your common base be a pure abstract class (which then opens a whole new
can of worms).
As you can see, access specifiers are employed to resolve the ambiguity.
This is specially critical should your common base be a pure abstract
class (which then opens a whole new can of worms).
Don't forget that unlike other languages, a pure abstract's member
functions can be implemented in C++.
#include
class Base
{
protected:
Base() { std::cout << "Base()n"; }
public:
virtual ~Base() { std::cout << "~Base()n"; }
virtual void ABC() = 0 { std::cout << "Base::ABC()n"; }
virtual void DEF() = 0 { std::cout << "Base::DEF()n"; }
};
class Der1 : public virtual Base
{
protected:
Der1() : Base() { std::cout << "Der1()n"; }
public:
~Der1() { std::cout << "~Der1()n"; }
virtual void ABC()
{
std::cout << "Der1::ABC()n";
Base::ABC();
}
};
class Der2 : public virtual Base
{
protected:
Der2() { std::cout << "Der2()n"; }
public:
~Der2() { std::cout << "~Der2()n"; }
virtual void DEF()
{
std::cout << "Der2::DEF()n";
Base::DEF();
}
};
class Der3 : public Der1, public Der2
{
public:
Der3() { std::cout << "Der3()n"; }
~Der3() { std::cout << "~Der3()n"; }
virtual void ABC()
{
std::cout << "Der3::ABC()n"; Der1::ABC();
}
virtual void DEF()
{
std::cout << "Der3::DEF()n"; Der2::DEF();
}
};
int main()
{
Der3 d3;
d3.ABC();
return 0;
}
/*
Base()
Der1()
Der2()
Der3()
Der3::ABC()
Der1::ABC()
Base::ABC()
~Der3()
~Der2()
~Der1()
~Base()
*/
Note: Der1 is managing the common Base's construction via its init list.
If ever you define Der1::ABC() as...
void Der1::ABC()
{
Base::ABC();
DEF();
}
The call to DEF() actually calls Der2::DEF() !!! Not Base::DEF(). Don't
ask.
and if you define it as...
void Der1::ABC()
{
ABC();
}
Then you have a circular call !!! Thats worse, much worse.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Krakers Guest
|
Posted: Thu Oct 20, 2005 11:28 am Post subject: Re: size of class having virtual functions |
|
|
"Carl Barron" wrote...
| Quote: |
Der3 is contains two instances of Base one each for Der1 and Der2.
Each instance of Base has a vtable with a pointer to a function.
[apparently 4 bytes, total == 8]
if you want:
Base
/
Der1 Der2
/
Der3
then class Der1:virtual public Base{...};
class Der2:virtual public Base{...};
class DEr3:publuc Der1,public Der2{...};
|
Yes, but don't expect sizeof(Der3) to be 4 in this case. Virtual
inheritance requires instances of Der1, Der2 and Der3 to be able
to locate their Base and this is an additional overhead. Visual
C++ shows the size of Der3, Der1 and Base as 12, 8 and 4.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|