0

This is an implementation for one base class and two derived classes:

#include <iostream>

using namespace std;

class myClass
{
    public:
    int f();
};

int myClass::f()
{ return 0;}

class mySubClass1
:public myClass
{
    public:
    int f();
};

int mySubClass1::f()
{return 1;}

class mySubClass2
:public myClass
{
    public:
    int f();
};

int mySubClass2::f()
{return 2;}

int main()
{
    myClass myClassObj;
    mySubClass1 mySubClass1Obj;
    mySubClass2 mySubClass2Obj;

    myClass* myClassPtr;
    myClassPtr = &myClassObj;
    cout << myClassPtr->f() << endl;
    myClassPtr = &mySubClass1Obj;
    cout << myClassPtr->f() << endl;
    myClassPtr = &mySubClass2Obj;
    cout << myClassPtr->f() << endl;

    return 0;
}

The output is:

0
0
0

while I expect

0
1
2

I know that it can be solved using virtual function; but I want to know Question: How the unexpected results above are related to memory allocation to the three objects? Why it doesn't return the expected results from a memory point of view?

Naghi
  • 145
  • 5

2 Answers2

2

The function declaration is searched in the class that corresponds to the static type of the pointer.

As a result the function declared in the base class is called independent on the dynamic type of the pointer.

You need to declare a virtual function to provide the dynamic typing.

For example

class myClass
{
    public:
    virtual int f();
};

//...

class mySubClass1
:public myClass
{
    public:
    int f() override;
};

//...
SergeyA
  • 61,605
  • 5
  • 78
  • 137
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

The size of an object in C++ does not depend on the amount of member functions the class has. Member functions are not "stored" inside an object instance, instead they are put somewhere in the final binary where they can be accessed from any object.

If you call a member function of a class, the compiler/linker will refer to that function for execution.

So how does an object know which function to call if there are virtual functions?

Objects of a class with virtual functions additionally have some hidden metadata (called vtable - how this is layed out is different among different compilers), which, among other things, saves pointers to the functions that should be called when you call a virtual function.

This is the mechanism how an object knows which virtual function to call (if any).

A demonstration of this hidden metadata can be seen from the difference in class size between a class with no virtual functions, and one that has a virtual function:

class foo {
    void bar();
};

class vfoo {
    virtual void vbar();
};

sizeof(foo);    // returns 1
sizeof(vfoo);   // returns 8

The 1 byte is because an object can not be sizeless, the 8 byte object basically consists of a pointer to the vtable.

MorningDewd
  • 501
  • 2
  • 6