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
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();
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
Related
i got a confuse about how does c++ compiler handle "this" pointer in virtual function, my code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class A {
public:
void print_A(void) {
cout << "A::THIS = " << this << endl;
return;
}
int a;
virtual ~A(void) {
return;
}
};
class B {
public:
virtual void print(void) {
cout << "B::THIS = " << this << endl;
return;
}
int b;
};
class C: public A, public B {
public:
void print(void) {
cout << "C::THIS = " << this << endl;
return;
}
int c;
};
class D {
public:
int d;
virtual ~D(void) {
return;
}
};
class E: public D, public C {
public:
int e;
virtual ~E(void) {
return;
}
};
void global_print(B *pb) {
cout << "pb = " << pb << endl;
pb->print();
return;
}
int main(int argc, char *argv[]) {
E e;
A *pa = &e;
B *pb = &e;
C *pc = &e;
D *pd = &e;
E *pe = &e;
cout << "pa = " << pa << endl;
cout << "pb = " << pb << endl;
cout << "pc = " << pc << endl;
cout << "pd = " << pd << endl;
cout << "pe = " << pe << endl;
pb->print();
pc->print();
pe->print();
global_print(&e);
return 0;
this is result compiled with g++ in my linux:
pa = 0x7ffc1e7c7a80
pb = 0x7ffc1e7c7a90
pc = 0x7ffc1e7c7a80
pd = 0x7ffc1e7c7a70
pe = 0x7ffc1e7c7a70
C::THIS = 0x7ffc1e7c7a80
C::THIS = 0x7ffc1e7c7a80
C::THIS = 0x7ffc1e7c7a80
pb = 0x7ffc1e7c7a90
C::THIS = 0x7ffc1e7c7a80
I can't understand that i send &e to global_print and pb in global_print is equal to 0x7ffc1e7c7a90. And then i invode pb->print(), the this pointer in global_print is 0x7ffc1e7c7a80 which is equel to pc. It seems that the pb->print() convert class B to class C, but class B is the father class of class C, how dose it convert?
And although pb can get addres of C::print by virtual function, it's only a address that havn't enough information to konw that is need to convert class B to class C, so how does the program konw that need to convert class B to class C in the run time?
THANKS a lot! wish have a nice day!
i have troubles with some methods after inherit.
It's hard (for me) to say where exactly problem is but i will try to expose this by example.
Minimal code:
#include <iostream>
class A
{
public:
A() {};
A(int x):val(x)
{
std::cout << "A constructor work" << std::endl;
}
int get()
{
std::cout << "Get A work" << std::endl;
return val;
}
protected:
int val;
};
class B: protected A
{
public:
B(int x) :A(x)
{
std::cout << "B constructor work" << std::endl;
test();
}
int get()
{
std::cout << "Get B work" << std::endl;
return A::get();
}
protected:
void test()
{
if (A::val == 0)
{
std::cout << "Test B work" << std::endl;
A::val = 1;
}
}
};
class C : protected A
{
public:
C() {};
C(int x) :A(x)
{
std::cout << "C constructor work" << std::endl;
test();
}
int get()
{
std::cout << "Get C work" << std::endl;
return A::get();
}
protected:
void test()
{
std::cout << "Test C work" << std::endl;
if (A::val != 0)
{
A::val += 2;
}
}
};
class D : private B, private C
{
public:
D(int x):B(x)
{
std::cout << "D constructor work" << std::endl;
C::test();
}
int get()
{
std::cout << "Get D work" << std::endl;
return B::get();
}
};
int main()
{
D d(0);
std::cout << d.get() << std::endl;
}
Output:
**A constructor work
B constructor work
Test B work
D constructor work
Test C work
Test C extra work
Get D work
Get B work
Get A work
1**
I expect val = 3 in the end, but it dont work like that.
I would be particularly grateful for your detailed reply.
Your class D contains two A objects - the one inherited by B and the one inherited by C
When you call C::test() you change the A object in C.
When you call D::get() - which calls B::get() - you inspect the value of the A object in B.
One way to get around this is by means of virtual inheritance. That is not something you want to mess with until you understand how multiple inheritance works, though.
How pointers are compared in C++?
The last line in the following code shows that values of b and c are different. However, b==c returns true.
#include <iostream>
struct A { int a; };
struct B { int b; };
struct C : A, B { };
int main() {
auto c = new C();
B* b = static_cast<B*>(c);
A* a = static_cast<A*>(c);
a->a = 1;
b->b = 2;
std::cout << c->a << c->b <<"\n";
std::cout << (a==c) << (b==c) << "\n";
std::cout << (long)a << "\n" << (long)b << "\n" << (long)c <<"\n";
}
A sample output that I received using GCC and Clang:
12
11
34073632
34073636
34073632
Don't cast pointers to long, cast them to intptr_t.
std::cout << (intptr_t)a << "\n" << (intptr_t)b << "\n" << (intptr_t)c <<"\n";
Anyhow, see this definition:
struct C : A, B { };
in memory that would look like:
{
A; [sizeof int]
B; [sizeof int]
}
Since A and B are both base classes of C, when you do this:
A* a = static_cast<A*>(c);
You get a pointer to the first 4 bytes of C. When you do this:
B* b = static_cast<B*>(c);
You get a pointer to the last 4 bytes of C, hence the difference. A pointer to type C will always implicitly cast the pointer this way.
I want to ask why the setX function here sets the x member variable in class A not the member variable x in class D even though I call setX function through D object?
How does the compiler did that ?
#include<iostream>
using namespace std;
class A
{
public:
int x;
A() { cout << "A cons" << endl; }
void setX(int i){ x = i; cout << "setxA" << endl; }
void print() { cout << x; }
};
class B : public A
{
public:
int x =30;
B() { cout << "B cons" << endl; }
};
class D : public B {
public:
D() {
cout << "D cons" << endl;
}
void func() {
setX(10);
cout << x << endl;
cout << B::x << endl;
cout << A::x << endl;
}
};
int main()
{
D d;
d.func();
return 0;
}
the output from this code is
30
30
10
This is called name hiding. Both A and B have a member x and both members always exist (you just cannot access them the same way). A knows about his member x and so the setX function sets exactly this member A::x. In B, you define another x which hides A::x. This means that if you do
B obj;
obj.x = 10;
or
D obj;
obj.x = 10;
you will access B::x both of the times (because B is lower in the inheritance hierarchy and therefore hides A::x).
Here is an example of how you can still access A::x using different casts.
#include <iostream>
struct A {
int x = 0;
void setX(int i) { x = i; }
};
struct B : A {
int x = 20;
};
int main()
{
B obj;
A castToA = static_cast<A>(obj);
A* castToAPtr = reinterpret_cast<A*>(&obj);
std::cout
<< "access via B: " << obj.x << "\n"
<< "access via A: " << castToA.x << "\n"
<< "access via A*: " << castToAPtr->x << "\n"
<< "access via B::(A::x): " << obj.A::x << "\n\n";
obj.setX(100);
std::cout << "set x to 100\n\n";
std::cout
<< "access via B: " << obj.x << "\n"
<< "access via A: " << castToA.x << "\n"
<< "access via A*: " << castToAPtr->x << "\n"
<< "access via B::(A::x): " << obj.A::x << "\n\n";
return 0;
}
which yields the output:
access via B: 20
access via A: 0
access via A*: 0
access via B::A::x: 0
set x to 100
access via B: 20
access via A: 0
access via A*: 100
access via B::A::x: 100
Your class B has an x and also A has an X. As this, you have two x in B!
So you may remove the x from your B class?
If you need both, you can access them with
A::x or B::x inside a method of B which you already did.
So your D class have also both x and calling setX calls the setX method of A. As in D you see the x from B which hides your x from A everything works as expected.
Your method A::setX did not know that you derive later from it. If you want to override the method, B has define a own B::setX which will then also be used in D.
Example how to override a method and access the parameter in derived class:
class A
{
public:
int x; // A::x
int y = 40; // A::y
// this function only knows about A::x
void setX(int i){ x = i; cout << "setxA" << endl; }
void setY(int i){ y = i; cout << "setyA" << endl; }
};
class B : public A
{
public:
int x =30; // this x ( B::x) hide A::x
int y =50; // this y hides also A::y
// now we override setY from A ( hiding setY from A! )
void setY(int i){ y = i; cout << "setyB" << endl; }
};
class D : public B {
public:
void func() {
setX(10); // Calls A::setX, as A::setX only knows about
// A::x it will access A::x
cout << "X" << std::endl;
cout << x << endl;
cout << B::x << endl;
cout << A::x << endl;
setY(90);
cout << "Y" << std::endl;
cout << y << endl;
cout << B::y << endl;
cout << A::y << endl;
}
};
int main()
{
D d;
d.func();
return 0;
}
Consider the following C++ code:
#include <iostream>
using std::cout;
class A
{
public:
int a;
A():a(0)
{
cout << "A constructor\n";
}
virtual void f()
{
cout << "f inside A\n";
}
};
class C : public A
{
public:
int c;
virtual void f()
{
cout << "f inside C\n";
}
C():c(0)
{
cout << "C constructor\n";
}
};
int main()
{
A varA = C();
cout << "Size of C class: " << sizeof(C) << "\n";
cout << "Size of varA object: " << sizeof(varA) << "\n";
C* varC = static_cast<C*>(&varA);
varC->f();
cout << "varC->a is " << varC->a << "\n";
cout << "varC->c is " << varC->c << "\n";
}
The output of this program is:
A constructor
C constructor
Size of C class: 16
Size of varA object: 8
f inside A
varC->a is 0
varC->c is 1726166356
I initialize the varA object with the constructor of class C. Constructors of A and C class are called, but the varA is a simply a A object. I cast the address of varA to C* type and I try to call its f() function, but it prints the f() function of class A, so I deduce that it is use the early binding mechanism to call it.
I think if I call the constructor of derived class, like this case, I obtain the same object if I had called the base constructor.
I think the only difference is the other constructors are called. Is my supposition right or there are any other differences?
Classic example of slicing. A varA = C(); leaves you with object of static and dynamic type of A. As a result, C* varC = static_cast<C*>(&varA); exhibits undefined behavior.
You can store a complete derived class in a base-class pointer, however:
int main() {
A* varA = new C();
C* varC = static_cast<C*>(varA);
varC->f();
cout << "varC->a is " << varC->a << endl;
cout << "varC->b is " << varC->b << endl;
cout << "varC->c is " << varC->c << endl;
} // oops, forgot to delete varA/varC, memory leak!