inheritance

V

vsgdp

Consider:

#include <iostream>
using namespace std;
class A
{
public:
A(){ p = this; }
static A* p;
};
A* A::p = 0;

class B : public A
{
public:
B() : A() {}
};

int main()
{
B b;
if( b.p == &b )
cout << "Equal." << endl;
}
Output: Equal.

Why does b.p point to b? It seems it should point to the "A" part of b.
That is, Stroustrup says "In this respect, the base class acts exactly like
a member of the dervied class." (page 306 in special edition).

However, the behavior of the program can be explained if we think of A() as
a "method" of B. But is that technically correct? Accelerated C++ says
constructors of a base class are not also members of the derived class.
 
V

Victor Bazarov

vsgdp said:
Consider:

#include <iostream>
using namespace std;
class A
{
public:
A(){ p = this; }
static A* p;
};
A* A::p = 0;

class B : public A
{
public:
B() : A() {}
};

int main()
{
B b;
if( b.p == &b )
cout << "Equal." << endl;
}
Output: Equal.

Why does b.p point to b?

It doesn't.
It seems it should point to the "A" part of b.

And it does.
That is, Stroustrup says "In this respect, the base class acts exactly like
a member of the dervied class." (page 306 in special edition).

However, the behavior of the program can be explained if we think of A() as
a "method" of B. But is that technically correct?
No.

Accelerated C++ says
constructors of a base class are not also members of the derived class.

The reason that the condition

b.p == &b

evaluates to 'true' is simple: both sides need to be of the same type to
participate in comparison. The left side is of type A*. So, the right
side is _converted_ to A* using the standard "pointer to derived to pointer
to base" conversion.

Your mistake is to think of addresses as typeless. They aren't.

Victor
 
V

vsgdp

The reason that the condition

b.p == &b

evaluates to 'true' is simple: both sides need to be of the same type to
participate in comparison. The left side is of type A*. So, the right
side is _converted_ to A* using the standard "pointer to derived to pointer
to base" conversion.

Your mistake is to think of addresses as typeless. They aren't.

Ok that makes sense, thanks. But what happens here then:

class A
{
public:
A(){ p = this; }
virtual void print(){cout<<"A::print \n";}
static A* p;
};
A* A::p = 0;

class B : public A
{
public:
B() : A() {}
virtual void print(){cout<<"B::print \n";}
};

int main()
{
A* a = new B();
A::p->print();
}

Output: B::print

Let me see if I can explain this (correct me if I'm wrong please):

A* a = new B();

Means 'a' points to an "A" instance, but its virtual table pointer points to
the table of B.

And
p = this;
means 'p' just points to what 'a' points to. So when

A::p->print();

is called, the function print is looked up in the vtable of B, and hence B's
print is called. Is that right?
 
V

Victor Bazarov

vsgdp said:
Ok that makes sense, thanks. But what happens here then:

class A
{
public:
A(){ p = this; }
virtual void print(){cout<<"A::print \n";}
static A* p;
};
A* A::p = 0;

class B : public A
{
public:
B() : A() {}
virtual void print(){cout<<"B::print \n";}
};

int main()
{
A* a = new B();
A::p->print();
}

Output: B::print

Let me see if I can explain this (correct me if I'm wrong please):

A* a = new B();

Means 'a' points to an "A" instance, but its virtual table pointer points to
the table of B.

And
p = this;
means 'p' just points to what 'a' points to. So when

A::p->print();

is called, the function print is looked up in the vtable of B, and hence B's
print is called. Is that right?

Yep.
 
V

Victor Bazarov

vsgdp said:
Just to clarify what I meant. 'a' points to the "A" part of a "B" instance
here, correct?
Yes.

Since it is legal to downcast:

B* b = (B*)a;

(a) I am not sure why you attempt to have the causality here, what
does "Since" mean? 'a' points to the "A" part of a "B" instance
because that's what happens when you convert a pointer to a derived
object to a pointer to a base one.

(b) You would be much better off without any C-style casts in your
code, believe me. The conversion back from an A* to a B* can be
made using either static_cast<B*> or dynamic_cast<B*>.

V
 
V

vsgdp

(a) I am not sure why you attempt to have the causality here, what
does "Since" mean? 'a' points to the "A" part of a "B" instance
because that's what happens when you convert a pointer to a derived
object to a pointer to a base one.


Ok, thanks for clearing up what exactly is happening.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,162
Messages
2,570,893
Members
47,432
Latest member
GTRNorbert

Latest Threads

Top