• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 318
  • Last Modified:

Looking for a polymorphic SizeOf operator

I am trying to determine the size of a derived class given a base class pointer.  As you know, when I call a virtual function with the base class pointer I will, through polymorphism, get the derived execution.  However, if I dereference the base-class pointer and ask for the size of the object using SizeOf, I get the size of the base class. For instance, the example below yields:

Size of *pBase = 88
Size of *pDerived = 248

#include <stdio.h>

class Base
{
public:
      Base() {}
      virtual ~Base() {}

protected:
      double m_BaseDouble[10];
};

class Derived : public Base
{
public:
      Derived() {}
      virtual ~Derived() {}

protected:
      double m_DerivedDouble[20];
};

int
main()
{
      Derived* pDerivedBase = new Derived;
      Base* pBase = pDerivedBase;
      Derived* pDerived = new Derived;

      int baseSize = sizeof(*pBase);
      printf("Size of *pBase = %d\n", baseSize);

      int derivedSize = sizeof(*pDerived);
      printf("Size of *pDerived = %d\n", derivedSize);

      return 0;
}

How can I get the size of the derived class (object) without having to overload the SizeOf operator?  How can I dynamically "upcast" to the derived class without actually knowing the derived class?  I want the results to yield

Size of *pBase = 248
Size of *pDerived = 248
     
0
JHaack
Asked:
JHaack
1 Solution
 
JHaackAuthor Commented:
Edited text of question
0
 
Tommy HuiEngineerCommented:
If you have access to the base and derived class, then it would be easier to add a virtual function that returns the size of the class.
0
 
JHaackAuthor Commented:
Let me reiterate.  I do not want to have to overload the SizeOf operator - or any other operator/function.  Your proposal simply provides a SizeOf operator with a different name.  I would still have to overload the size retrieval function in each derived class.  What I really need is a way of using the base-class pointer polymorphically to determine the size of the derived object.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
nietodCommented:
I have to agree with thui.  You want polymorphic behavior.  Virtual functions are what provide polymorphic behavior.  Just add a virtual function to each class called GetSizeOf(), for example.  You should be able to use templates to create the function for each class (base and derived).
0
 
JHaackAuthor Commented:
I don't disagree with either thui or nietoid, but I'm aware of the possibility of adding a virtual function and, let me state it again - that is not the answer to my question.  I want a global way of determining the size of a derived object given a pointer to it's base class (say CObject).  Adding a virtual function adds overhead to my current classes and every future class that I develop and it requires me to rewrite all third party classes that I am currently using - ultimately opening up the door for some errors.  Again, I do not want an answer that involves a virtual function.  I want an answer that takes the base-class pointer and uses it to determine the type of the derived class.
0
 
LucHoltkampCommented:
The best solution is to add a virtual to the baseclass and derived classes:
virtual size_t SizeOf() { return sizeof(*this); }

If you don't want to do this you can write a function that checks for the type. The disadvantage is that you have to know the classhierarchy.

class A {int a; };
class B : public A {int b; };
class C : public B {int c; };

long SizeOf(A *aPtr)
{
  if (typeid(*aPtr) == typeid(A)) return sizeof(A);
  else if (typeid(*aPtr) == typeid(B)) return sizeof(B);
  else if (typeid(*aPtr) == typeid(C)) return sizeof(C);
  else return -1; // Unknown class,
}

or dynamically:

Create a static container containing objects that combine the name of a class and its size. When you need the size of an object you could look it up by its name, using typeid. Adding classes to the container could be done with a macro that inserts the data in the container.

/* Header file (sizeof.hpp) */

#include <stddef.h>
#include <typeinfo.h>

// adds an entry to the container. The returned (dummy)int is
// used to initialize the dummy static. This trick is to get code
// running without using startup pragma's
int register_sizeof(const char* class_name, size_t sizeof_class);

// retrieve the size of a class by looking it up in the container.
size_t size_of(const char* class_name);

// add this macro for each class you want to get the size of in a code file, ie
// REGISTER_SIZE(MyClass);
#define REGISTER_SIZE(a)  \
  static int dummy_##a = register_sizeof(typeid(a).name(), sizeof(a))

// you call this function if you want to know the size of some object
//
template<class T>
inline size_t SizeOf(T&)
{
  return size_of(typeid(T).name());
}

/* End of Header */

/* Code File (sizeof.cpp) */



#include <utility>
#include <map>
#include "sizeof.hpp"

static map<string, size_t> sizes;

int register_sizeof(const char* class_name, size_t its_size)
{
  sizes.insert(pair<string, size_t>(string(class_name), its_size));
  return 0;
}

size_t size_of(const char* class_name)
{
  return sizes.find(string(class_name));
}

/* End of Code file */

.luc.
0
 
nietodCommented:
I can see your delema.  (I'm not sure I can spell it, but I can see it).  Unfortunately, I don't think there is a solution.  If there is, its going to have to involve templates.  But I don't see a way without templates and virtual functions.  

Perhaps there is a different angle, though.  What are you trying to do that you need this?  
0
 
JHaackAuthor Commented:
I'm using it to include memory tracking throughout my application.  Specifically, two functions - Allocate and Deallocate - will be used in place of new and delete (or malloc and free) and will track the amount and blocks of memory allocated and deallocated..  Generally,

Deallocate(Base* p)
{
  bytes -= sizeof(*p);
  delete p;
}


0
 
JHaackAuthor Commented:
I would have given you an A, but your solution requires some overhead in "registering" the classes.  However, your suggestion is probably the best, or at least as good as any.  It would be nice if the ANSI standard was revised to require that new and delete (malloc and free) return the amount of memory which was allocated or released.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now