user1999934
user1999934

Reputation: 33

Class casting in virtual functions c++

Hi I have the following piece of code -

class A{
public:
    A(){
        cout << "In A CTR" << endl;
       }

    virtual void buildTree() = 0;

    void print(){
    cout << "int A print  This = " << this << endl;
    }
};


class B{
public:
    B(){
        cout << "In B CTR" << endl;
    }
    virtual A* getBuilder() {
        cout << " In B getBuilder , this = " << this << endl;
        return NULL;
    }
    virtual void hell(){
        cout << "In B hell This =" << this << endl;
    }
    void print(){
        cout << "in B print This = " << this << endl;
    }
    B* add(B* child){
        cout << "In B add , This = " << this <<endl;
    }
};

class C : public A, public B{
public:
    C(){
        cout << "In C CTR" << endl;
    }
    A* getBuilder() {
        cout << "In C getBuilder , this = " << this << endl;
        return this;
    }
    void print(){
        cout << "In C print  This = " << this << endl;
    }
};

class D : public C{
public:
    D(){
        cout <<"In D CTR" << endl;
    }
    void buildTree(){
        cout << "buildTree in D , This = "  << this << endl;
        B *b = NULL;
        add(b);
    }
    void print(){
        cout << "In D print  This = " << this << endl;
    }
};

int main() {
 B *root = new D();
 root->getBuilder()->buildTree();
 return 0;
}

I get the following output :

In C getBuilder , this = 0x7f9aa0500100

buildTree in D , this = 0x7f9aa0500100

In B add , this = 0x7f9aa0500108

I am unable to figure out , why the add() in class B is called . Here is my understanding . Please correct me.

root is a pointer of type B and points to D . So, when root->getBuilder() is called , it calls the virtual function in class C , which returns a pointer of type A* .

So, now root->getBuilder() returns a pointer of type A pointing to D. Hence root->getBuilder()->buildTree() is able to call buildTree in D .

But in the buildTree in class D , we are calling add which is defined in class B. How are we able to call this , as the pointer type is A and should not know nothing about B, functions .

Any help is appreciated.

Thanks

Upvotes: 0

Views: 122

Answers (2)

Some programmer dude
Some programmer dude

Reputation: 409482

What you have is basically this (very simplified):

struct B
{
    B* add(B*)
    {
        std::cout << "B::add\n";
    }
};

struct C : B
{
    // Nothing relevant
};

struct D : C
{
    void buildTree()
    {
        add(NULL);
    }
};

int main()
{
    D root;
    root.buildTree();
}

The class D is a C. The class C is a B. That means D is a B as well. Therefore D has the member function add.

The pointers and indirection are red herrings in the case of how you can call add from a D member function.


I think I see the problem now, and it's about the interface the classes present to the world.

Again with a basic and simplified example:

struct A
{
    void funA();
}

struct B
{
    // Nothing relevant
};

struct C : A, B
{
    // Nothing relevant
};

Then by doing

B* p = new C;

is valid. But even though the pointer p is pointing to an object of C (which is also an A) it does not have the interface of A (or C for that matter), only of B.

If you want to use the functions in A or C you have to use down-casting to cast it to the correct type:

static_cast<D*>(p)->funA();  // Cast to the type `p` *really* is

Upvotes: 1

keith
keith

Reputation: 5352

This seems to be the question:

But in the buildTree in class D , we are calling add which is defined in class B. How are we able to call this , as the pointer type is A and should not know nothing about B, functions.

Calling buildTree on a pointer type of A* where buildTree is marked as virtual is going to call buildTree on a D* given root is of type D. So add is available to D because D can access the public and protected methods of is superclasses.

The original code example is unnecessarily complicated. The same principle can be examined via the following code:

A *root = new D();
root->buildTree();

Upvotes: 1

Related Questions