I got told that if i do inheritance when the base class contains protected member variables and a child class will construct the base class, it will duplicate it's members in memory. Example:
class Animal
{
public:
virtual std::string& sound() { return m_sound; }
virtual void setSound(std::string& sound) { m_sound = sound; }
virtual int age() { return m_age; }
virtual void setAge(int age) { m_age = age; }
protected:
Animal(std::string sound, int age) : m_sound(sound), m_age(age) { }
int m_age;
std::string m_sound;
};
class Dog : public Animal
{
public:
Dog(int speed) : Animal("Waff!!", 3), m_speed(speed) {}
virtual int speed() { return m_speed; }
virtual void setSpeed(int speed) { m_speed = speed; }
protected:
int m_speed;
};
So using the example above, what I meant in other words, that if I create a Dog
object, it'll allocate 2 times memory for m_sound and m_age.
That completely didn't make any sense to me and I've been wondering why would the compiler would do such a thing unless the information I heard is misleading.
So say in main we create:
Dog bulldog(5);
Debugging this code and looking at the memory here is what I got:
I would like to know what exactly gets allocated in the region of memory where the questions marks between the parent class data and the child.
I got told that if i do inheritance when the base class contains protected member variables and a child class will construct the base class, it will duplicate it's members in memory. ... it'll allocate 2 times memory for
m_sound
andm_age
.
Nope. In your example, every object of type Dog
contains just two subobjects of int
and one subobject of type std::string
. A compiler would technically be allowed to use more storage than necessary, but there would be no reason to, and the program would not be allowed to have different addresses for the same member or multiple std::string
constructor or destructor calls.
Without knowing your source, there's not much more to say about that.
What exactly gets allocated in memory where the questions marks between the parent class data and the child?
The details depend on your compiler and standard library, but most likely all or most of the bytes between what you identified as m_age
and m_speed
belong to the std::string m_sound
member subobject. That is, I'm guessing that if you did std::cout << sizeof(std::string) << "\n";
, you would get 28 or close to it.
Because of the way the C++ object model works, sizeof(std::string)
is a constant, and every std::string
only gets a fixed number of bytes, but a string can "contain" many characters. This normally means the std::string
has a char*
pointer to dynamically allocated memory which holds the actual characters. It will in general also need a way to know the length of the string and the capacity of the dynamically allocated buffer.
But as you noticed, the character values of your string actually appear within the memory of the std::string
object directly, which probably means your standard library implementation is using the Small String Optimization: a std::string
can contain either a char*
pointer and length and capacity, or a certain number of character values directly. (This can reduce the need to dynamically allocate and deallocate memory, which can take a lot of CPU time if used often enough.) The std::string
will also need some way of knowing whether it's currently in pointer mode or direct storage mode, and that information is presumably somewhere in the later bytes.
To decipher exactly what each byte in a std::string
means, you would need to look up the definition of class template std::basic_string
in the header files used by your compiler.