Size of an inherited class ?

  • Thread starter =?iso-8859-1?Q?Fran=E7ois_Fleuret?=
  • Start date
?

=?iso-8859-1?Q?Fran=E7ois_Fleuret?=

Dear all,

I fear this is a question which has been asked zillions of
times. However, it seems to me to be such a legitimate feature that I
can't imagine it is impossible.

How can one know the size of an object in a "virtual" manner ?

For instance, how can I write a virtual function print_size(); which
prints the size of *this, and which will print the correct value with
an object of an inherited class ?

Thanks in advance for any hint,
 
M

Michiel.Salters

François Fleuret said:
Dear all,

I fear this is a question which has been asked zillions of
times. However, it seems to me to be such a legitimate feature that I
can't imagine it is impossible.

How can one know the size of an object in a "virtual" manner ?

For instance, how can I write a virtual function print_size(); which
prints the size of *this, and which will print the correct value with
an object of an inherited class ?

You can't, because you can't do anything useful with it. sizeof() is
used to allocate memory for new objects (before you can even call
print_size()) or memcpy existing objects (which you can't do if it has
virtual functions).

What legitimate use did you imagine?

HTH,
Michiel Salters
 
J

John Carson

François Fleuret said:
Dear all,

I fear this is a question which has been asked zillions of
times. However, it seems to me to be such a legitimate feature that I
can't imagine it is impossible.

How can one know the size of an object in a "virtual" manner ?

For instance, how can I write a virtual function print_size(); which
prints the size of *this, and which will print the correct value with
an object of an inherited class ?

Thanks in advance for any hint,

This seems to work

#include <iostream>
using namespace std;

struct Base
{
int b;
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};


struct Derived : Base
{
int array[4];
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};

int main(int argc, char* argv[])
{
Base b;
Derived d;

Base * pb1 = &b;
Base * pb2 = &d;

pb1->Print_Size();
pb2->Print_Size();
return 0;
}
 
P

peter koch

(e-mail address removed) skrev:
You can't, because you can't do anything useful with it. sizeof() is
used to allocate memory for new objects (before you can even call
print_size()) or memcpy existing objects (which you can't do if it has
virtual functions).

What legitimate use did you imagine?

It is difficult to find a use for that size, but perhaps some sort of
clone:

class base
{
public:
virtual ~base() = 0;
virtual int size() = 0;
virtual void clone(void* adress) = 0;
};

void silly(base* b)
{
void* clonemem = malloc(b->size());
b->clone(clonemem);
}


/Peter
 
?

=?iso-8859-1?Q?Fran=E7ois_Fleuret?=

Dear John,

You wrote on 13 Mar 2006 12:51:47 MET:
This seems to work

#include <iostream>
using namespace std;

struct Base
{
int b;
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};


struct Derived : Base
{
int array[4];
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};

int main(int argc, char* argv[])
{
Base b;
Derived d;

Base * pb1 = &b;
Base * pb2 = &d;

pb1->Print_Size();
pb2->Print_Size();
return 0;
}

Yeah, but since sizeof used the static type of the class, you have to
re-write the method Print_Size -- with the exact same code -- in the
derived class.

I was wondering if there was a way to access the information about the
class size from its virtual table.

Cheers,
 
R

Rolf Magnus

François Fleuret said:
Dear John,

You wrote on 13 Mar 2006 12:51:47 MET:
This seems to work

#include <iostream>
using namespace std;

struct Base
{
int b;
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};


struct Derived : Base
{
int array[4];
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};

int main(int argc, char* argv[])
{
Base b;
Derived d;

Base * pb1 = &b;
Base * pb2 = &d;

pb1->Print_Size();
pb2->Print_Size();
return 0;
}

Yeah, but since sizeof used the static type of the class, you have to
re-write the method Print_Size -- with the exact same code -- in the
derived class.

That's right. You could use templates to avoid that:

template<typename T>
struct Base
{
int b;
virtual void Print_Size() const
{
cout << sizeof(T) << endl;
}
};

struct Derived : Base<Derived>
{
//...
};
I was wondering if there was a way to access the information about the
class size from its virtual table.

No. The C++ standard doesn't even define the term "virtual table" or
anything similar.
 
J

John Carson

Rolf Magnus said:
François Fleuret said:
Dear John,

You wrote on 13 Mar 2006 12:51:47 MET:
This seems to work

#include <iostream>
using namespace std;

struct Base
{
int b;
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};


struct Derived : Base
{
int array[4];
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};

int main(int argc, char* argv[])
{
Base b;
Derived d;

Base * pb1 = &b;
Base * pb2 = &d;

pb1->Print_Size();
pb2->Print_Size();
return 0;
}

Yeah, but since sizeof used the static type of the class, you have to
re-write the method Print_Size -- with the exact same code -- in the
derived class.

That's right. You could use templates to avoid that:

template<typename T>
struct Base
{
int b;
virtual void Print_Size() const
{
cout << sizeof(T) << endl;
}
};

struct Derived : Base<Derived>
{
//...
};


This works nicely for Derived objects. But how do you declare a Base object?
 
R

Rolf Magnus

John said:
Rolf Magnus said:
François Fleuret said:
Dear John,

You wrote on 13 Mar 2006 12:51:47 MET:

This seems to work

#include <iostream>
using namespace std;

struct Base
{
int b;
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};


struct Derived : Base
{
int array[4];
virtual void Print_Size()
{
cout << sizeof(*this) << endl;
}
};

int main(int argc, char* argv[])
{
Base b;
Derived d;

Base * pb1 = &b;
Base * pb2 = &d;

pb1->Print_Size();
pb2->Print_Size();
return 0;
}

Yeah, but since sizeof used the static type of the class, you have to
re-write the method Print_Size -- with the exact same code -- in the
derived class.

That's right. You could use templates to avoid that:

template<typename T>
struct Base
{
int b;
virtual void Print_Size() const
{
cout << sizeof(T) << endl;
}
};

struct Derived : Base<Derived>
{
//...
};


This works nicely for Derived objects. But how do you declare a Base
object?

Oh, I forgot. You need a third class that is the base to all Base<> template
instances. Here is a complete and tested example:

#include <iostream>

using std::cout;
using std::endl;

struct Base
{
virtual void Print_Size() const = 0;
virtual ~Base() {}
};

template<typename T>
struct TBase : Base
{
virtual void Print_Size() const
{
cout << sizeof(T) << endl;
}
};

struct Derived : TBase<Derived>
{
//...
int arr[32];
};

int main()
{
Base* test = new Derived;
test->Print_Size();
delete test;
}
 
J

John Carson

Rolf Magnus said:
John said:
This works nicely for Derived objects. But how do you declare a Base
object?

Oh, I forgot. You need a third class that is the base to all Base<>
template instances. Here is a complete and tested example:

#include <iostream>

using std::cout;
using std::endl;

struct Base
{
virtual void Print_Size() const = 0;
virtual ~Base() {}
};

template<typename T>
struct TBase : Base
{
virtual void Print_Size() const
{
cout << sizeof(T) << endl;
}
};

struct Derived : TBase<Derived>
{
//...
int arr[32];
};

int main()
{
Base* test = new Derived;
test->Print_Size();
delete test;
}


You still haven't used a Base object. I am not sure in what way this version
improves on the earlier one.

Further, what happens with your scheme if you need a second level of
derivation: a Derived2 that derives from Derived?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,438
Messages
2,571,699
Members
48,796
Latest member
Greg L.
Top