C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

size of class having virtual functions

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Keshav
Guest





PostPosted: Mon Oct 17, 2005 1:59 pm    Post subject: size of class having virtual functions Reply with 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


[ 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





PostPosted: Tue Oct 18, 2005 10:22 am    Post subject: Re: size of class having virtual functions Reply with quote



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





PostPosted: Tue Oct 18, 2005 10:30 am    Post subject: Re: size of class having virtual functions Reply with quote



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





PostPosted: Tue Oct 18, 2005 10:36 am    Post subject: Re: size of class having virtual functions Reply with quote

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





PostPosted: Tue Oct 18, 2005 10:36 am    Post subject: Re: size of class having virtual functions Reply with quote

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
Quote:
|
Der1 Der2

/
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





PostPosted: Wed Oct 19, 2005 8:48 am    Post subject: Re: size of class having virtual functions Reply with quote


"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





PostPosted: Thu Oct 20, 2005 11:28 am    Post subject: Re: size of class having virtual functions Reply with quote

"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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.