0

Firstly I am a beginner, but very enthusiastic about coding.

I have this base class from which several classes are inherited. A function is written in base class which requires the size of the called object. At the time of coding of the function, the size is unknown as the function may be called by objects of different derived classes. Until now, I have been passing the size as an argument, but the should be some way around.

I tried sizeof(*this), but sizeof(*this) returns an entirely different value which is neither the size of the base class nor the size of the derived class. I am confused.... Any Explanations?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
daltonfury42
  • 3,103
  • 2
  • 30
  • 47
  • use **sizeof(ClassName)** – Deidrei Dec 06 '13 at 08:46
  • 1
    How do you know it's not the size of either of the classes? Maybe you are the victim of the ["no-padding assumption"](http://stackoverflow.com/questions/5596428/sizeofstruct-returns-unexpected-value)? –  Dec 06 '13 at 08:47
  • http://stackoverflow.com/questions/937773/how-do-you-determine-the-size-of-an-object-in-c – Nick Louloudakis Dec 06 '13 at 08:48
  • Actually `sizeof(*this)` is the correct thing. That, or a hack involving the curiously recurring template pattern. But why complicated when you can do it simple? The compiler does bookkeeping so it always knows what `this` is, and it sure also knows the size of the object. – Damon Dec 06 '13 at 08:55

3 Answers3

3

You can write a virtual function that will return the size of an object

struct Base
{
    virtual size_t size() const { return sizeof( *this ); }
    virtual ~Base(){}
};

struct Derived1 : Base
{
    virtual size_t size() const { return sizeof( *this ); }
    int x;
};

struct Derived2 : Base
{
    virtual size_t size() const { return sizeof( *this ); }
    int x;
    int y;
};

Base *b  = new Base;
Base *b1 = new Derived1;
Base *b2 = new Derived2;

std::cout << "b->size() = " << b->size() << std::endl;
std::cout << "b1->size() = " << b1->size() << std::endl;
std::cout << "b2->size() = " << b2->size() << std::endl;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I am a beginner, so 1) What is size_t? 2) Why did you make it const? What is the problem if it is not const? – daltonfury42 Dec 06 '13 at 12:29
  • size_t is a typedef of an implementation-defined unsigned integral type. It is the type that is returned by operator sizeof. Qualifier const for member functions of classes means that functions do not change any data member of classes. For example if an object defined as constant then you may call only those member functions of the class that has qualifier const because constant objects may not be changed. – Vlad from Moscow Dec 07 '13 at 06:59
0

Just use the sizeof() operator, with the classname. You can find the sizeof any class with this.

size = sizeof(ClassName);
Aswin Murugesh
  • 10,831
  • 10
  • 40
  • 69
  • 2
    The problem is, what is `ClassName`? Since the function is to be placed in a base class, the only _known_ name is the base class' name. It's not necessarily the one the OP wants, though. The function might be called on a derived class object. – Damon Dec 06 '13 at 08:57
  • @Damon: The classes have to be declared at the top, before defining any class. This solved the problem right? – Aswin Murugesh Dec 06 '13 at 09:01
  • Not really, the OP wants to have a function in the base class that is later called on some object of a derived type. Of course you do not know that type at the time of writing this function, nor can you predict what type some piece of client code may call this function on. – Damon Dec 06 '13 at 09:04
0

Ok, I'll try for an answer.

Acoording to this link: sizeof *this object

sizeof is calculated at compile time, so your function will always be using the size of the Base-object (unless your function is overriden in a subclass).

So the best solution is to use templates. As Damon pointed out in a comment, the curiously recurring template pattern is the solution here:

template <class ActualClass>
class Base
{
  size_t mySize() const { return sizeof(ActualClass); }
}

class Derived : public Base<Derived>
{
};

EDIT: This has the downside, that your common base class will actually be a different class for each Derived.

Community
  • 1
  • 1
user1781290
  • 2,674
  • 22
  • 26
  • 1
    I'm not sure it's a good idea, but one way to avoid your downside is to create a non-template `Base` class, and make `Base` derive from that. That way, every class still derives from `Base`. –  Dec 06 '13 at 09:17
  • That will solve the problem indeed, but don't forget to make `mySize()` virtual then – user1781290 Dec 06 '13 at 09:20