Click here to Skip to main content
15,880,967 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Please experts clear my doubts.
I don't understand why it throws compilation error. These are polymorphic classes, in main I assigned base pointer with a derived class pointer, it should find func_2 as __vptr of base will point to __vtable of derived class.
Or I have some gap in my understanding of __vtable and __vptr.
Please suggest me some good articles to clear my below doubts.
C++
class base
{
  public:
     virtual int func_1()
       {
         cout << "In func_1" ;
       }
};
class deri: public base
{
    public:
        virtual int func_2()
        {
          cout << "in func_2"; 
        }
};

main()
{
 base *ptr = new deri;
 ptr->func_2();//ptr is pointing to derived object
}


What I have tried:

I tried compiling it, it throws compilation error:
C++
main.cpp: In function ‘int main()’:
main.cpp:32:6: error: ‘class base’ has no member named ‘func_2’
 ptr->func_2();
      ^
Posted
Updated 22-Nov-18 21:14pm
Comments
Member 13913102 23-Nov-18 4:01am    
vtable explanation which I learnt is here:
http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/

Oh boy, you got polymorphism and type safety all confused up there. What you are expecting to happen is wrong, that is not why a type is inherited. Inheritance works from parent, to child. So a function in parent, is guaranteed—let's ignore the access modifiers in inheritance for a minute—in the child type, but not the other way around. You cannot call a child function from a parent type. Parent type just doesn't know what that function is. So,
C++
class Foo { 
   int a;
   int b;
};

class Bar {
   string name;
};
In the code above, you can do this,
C++
Bar b;
cout << b.a; // a comes from Foo
But you cannot do this,
C++
Foo f;
cout << f.name; // name does not exist
But, in inheritance, polymorphism works just fine. So in your code, if we do this,
C++
class deri : public base
{
public:
    int func_1() override  // <-- let's override, since base has it virtual
    {
        cout << "Derived func_1";
        return 0; // <-- Why did you forget this and didn't complain? 
    }

Now, when you run the same code,
C++
base* base = new deri;
base->func_1();
It would print, "Derived func_1". Why? Because of polymorphism.

I do not want to indulge you in the details of C++ memory model, because all this detail is applied there. Just remember, inheritance works from parent to child, but polymorphism forces that the function calls be done on the actual instance type—in your case new deri;.

Please see the links below, to learn a bit more on this concept,
Polymorphism (computer science) - Wikipedia[^]
Type safety - Wikipedia[^]
Memory model - cppreference.com[^]
c++ - How does inheritance actually work? - Stack Overflow[^]
Friendship and inheritance - C++ Tutorials[^]
 
Share this answer
 
Comments
Member 13913102 23-Nov-18 3:00am    
thx for your detailed explanation, I will go thru your answer again, I still have few doubts.
If in base class I rename func_1 as func_2, then this will work fine and derived class function will be called, as concepts of __vtable and __vptr make it happen. __vptr will have address of __vtable of derived class.
But before renaming func_1 to func_2(in original code), why __vptr was not able to find virtual func_2

vtable explanation which I learnt is here:
http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/
Afzaal Ahmad Zeeshan 23-Nov-18 3:57am    
If in base class I rename func_1 as func_2, then this will work fine and derived class function will be called

No, but because now base type will have a func_2, and not func_1. In this case, if you try calling func_1 on base, it will give the same error.

I am unsure what you mean by the last sentence in first paragraph. Virtual table is created for the type that is created, as in your case, it was derived type. Thus, the virtual table was created for deri type and caused it to know the functions. But when you are trying to call the func_2, the base type does not have any information of that.

Remember, virtual table exists on runtime. This error is being caused on compile time, thus virtual table concept does not exist just yet. Upon building and executing the program, your virtual table takes control and C++ memory model makes the program take polymorphism.
Member 13913102 23-Nov-18 4:10am    
yes I agree with you. This means first compiler should agree it, vtable comes in picture at runtime.
Thx for your valuable comments and answers.
Afzaal Ahmad Zeeshan 23-Nov-18 4:13am    
Yes, you are right.

Please also try marking the answers as solution if they helped you out.
In order to make polymorphism work the method name (and signature) must be the same. Being ptr a actual deri pointer, you might still access its func_2 method via downcast, but that's not polymorphism:
C++
#include <iostream>
using namespace std;

class base
{
  public:
     virtual void func_1()
       {
         cout << "In func_1 of base.\n" ;
       }
};
class deri: public base
{
    public:
        virtual void func_1() override
        {
          cout << "in func_1 of deri.\n";
        }
        virtual void func_2()
        {
          cout << "in func_2 of deri.\n";
        }

};

int main()
{
 base *ptr = new deri;
 ptr->func_1();//ptr is pointing to derived object
 (dynamic_cast<deri *>(ptr))->func_2(); // this is not polymorphism, though.
}
 
Share this answer
 
Comments
Member 13913102 23-Nov-18 3:59am    
yes I missed on polymorphism, but see this link, it says __vptr will point to __vtable of derived class, and this __vtable will have pointer to func_2, then it must be accessed.
http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/
CPallini 23-Nov-18 4:05am    
In fact it is accessible, as my code shows.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900