Reputation: 33
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
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
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