Using Ptr of derived class to point to base class and viceversa

B

Bhan

Using Ptr of derived class to point to base class and viceversa
class base
{
....
}
class derived : public base
{
....
}

I want to know any practical scenario when this is used
a. B b;
D *p = &b;

b. B *b;
D d;
b = &d;



Can any one explain it?I know it is theoritically OK.But i am not able
why to do such things?

Thanks in Advance,
Bhanu
 
P

placid

Bhan said:
Using Ptr of derived class to point to base class and viceversa
class base
{
...
}
class derived : public base
{
...
}

I want to know any practical scenario when this is used
a. B b;
D *p = &b;

b. B *b;
D d;
b = &d;



Can any one explain it?I know it is theoritically OK.But i am not able
why to do such things?

doesnt this lead to the Slicing Problem ?
 
G

Gianni Mariani

No practical use of downcasting from an object not of the derived type.

Upcasting: Happens all the time.
doesnt this lead to the Slicing Problem ?

Slicing happens when you copy the object. The OP is simply taking
pointers to the object.
 
B

Bhan

So you mean this is normally used?
Upcasting: Happens all the time.

B b;
D *p = &b;
But why do this ?why not have a ptr to base class itself ?(below)

B b;
B *p = &b;

Can you give the use of these two?
B b;
B *p = &b;
D *p = &b;
 
J

John Carson

Bhan said:
Using Ptr of derived class to point to base class and viceversa
class base
{
...
}
class derived : public base
{
...
}

I want to know any practical scenario when this is used
a. B b;
D *p = &b;

You shouldn't do this because the derived class will usually have members
that the base class does not. The derived class pointer will allow you to
try to access members of the derived class than don't exist in the base
class object, with possibly disastrous consequences.
b. B *b;
D d;
b = &d;

This is safe and very useful, though it rarely occurs in the context that
you have shown. It occurs in two main contexts.

1. Containers of pointers. The container (an array or vector or whatever)
can usually only store pointers of a single type. If you want it to point to
both base and derived class objects, then you store base pointers and assign
to those base pointers the addresses of both base and derived class objects.
You can then iterate over all the members in the container, calling the same
function for each. If the function is virtual, then you can get a different
function for the pointers pointing to the derived class objects as compared
to the pointers pointing to the base class objects (this is known as
run-time polymorphism). For non-virtual functions, you get the same function
in both cases, but this is OK since the function is a member of both the
base and the derived class (with public inheritance, any public function in
the base class becomes a public function in the derived class).

2. Functions that take pointer arguments. Given, say:

Base b;
Derived d;

void foo(Base *ptr)
{
ptr->MemberFunction();
}

you can call this function using the address of either a base class or a
derived class object:

foo(&b);
foo(&d);

The effect of the first is:

ptr = &b;
ptr->MemberFunction();

The effect of the second is:

ptr = &d;
ptr->MemberFunction();
 
B

Bhan

b. B *b;
D d;
b = &d;
Can I summarize my understanding like this?

Whenever you have the provision to store only base ptr,store the base
ptr that points to dervied object.

When u retrieve it,use static_cast and get the req derived object.Right?
 
J

John Harrison

Bhan said:
b. B *b;


Can I summarize my understanding like this?

Whenever you have the provision to store only base ptr,store the base
ptr that points to dervied object.

When u retrieve it,use static_cast and get the req derived object.Right?

static_cast if you are sure that the pointer points to the derived
class. Use dynamic_cast if you are not sure and you have a polymorphic
base class.

john
 
J

John Carson

Bhan said:
b. B *b;
Can I summarize my understanding like this?

Whenever you have the provision to store only base ptr,store the base
ptr that points to dervied object.
Yes.

When u retrieve it,use static_cast and get the req derived
object.Right?

Most of the time you don't need any cast. You call functions that are
declared in the base class and may or may not be virtual.

If you want to call a derived class function that does not exist in the base
class --- or does exist but is not virtual --- then a cast is necessary. See
John Harrison's remarks on this.

Note that these issues only arise in situations where you don't
automatically know the type of object pointed to, as with a container of
pointers that can point to both base and derived class objects. In such
contexts, it is simplest if you can make the same function call regardless
of what the pointer points to and you achieve different behaviour by using
virtual functions. Having to figure out what is pointed to --- and making
different function calls on that basis --- is inelegant and error prone.

If you have derived objects and only derived objects and you know it, then
you just use pointers to derived objects (if you use pointers at all) and
none of these complications arise.
 
G

Greg

Bhan said:
b. B *b;
Can I summarize my understanding like this?

Whenever you have the provision to store only base ptr,store the base
ptr that points to dervied object.

When u retrieve it,use static_cast and get the req derived object.Right?

One thing to remember of course is that a pointer to a derived class is
also a pointer to the base class. It can be used anywhere a base class
pointer can be used. An instance of the derived class is an instance of
the base class.

And while "downcasts" from a base class to a derived class are
sometimes necessary, using them is not considered a good programming
practice. A lot of downcasts in source code generally indicate a
weakness in the program's class hierarchy or implementation. After all,
if the client has a base pointer it should not need to "know" about its
derived classes. That is the whole point of having an abstraction in
the first place. On the other hand if a client does need an object of
the derived class for some reason, then the question becomes how did it
wind up with a pointer to the base class.

Greg
 
B

Bhan

Thats fine.
I am satisfied with this.
So,Can I summarize my understanding like this?


Whenever you have the provision to store only base ptr,store the base
ptr that points to dervied object.


When u retrieve it,use dynamic_cast or static_cast(depending on the
situation)and get the req derived object.Right?

Thanks
Bhanu
 
M

mlimber

Bhan said:
b. B *b;
Can I summarize my understanding like this?

Whenever you have the provision to store only base ptr,store the base
ptr that points to dervied object.

When u retrieve it,use static_cast and get the req derived object.Right?

If I understand you correctly, I don't think your statement is
accurate. You shouldn't always refer to a derived class with a base
class pointer just because you can do so. Certainly, one of the main
reasons for using inheritance is to allow abstraction from the
specifics of derived classes, but this is generally done by using
virtual functions to create interfaces for the derived classes to
implement.

Casting back to the derived type from a pointer to the base class is
generally discouraged. If you need to refer to the derived object as
the derived type, not as the more general base type, then generally
speaking you should not be using a pointer to the base class at that
point in the code.

Consider:

// Abstract base class; cannot be instantiated
struct Shape { virtual void Draw() const = 0; }

// A concrete class
struct Square : public Shape
{
Square( float length ) : length_( length ) { /* ... */ }

// Implement the virtual function
void Draw() const { /*...*/ }

// An additional function that applies to Squares
void Rotate( float angle ) { /*...*/ }

private:
const float length_;
};

// Another concrete class
struct Circle : public Shape
{
Circle( float radius ) : radius_( radius ) { /* ... */ }
void Draw() const { /*...*/ }
private:
const float radius_;
};

Now you can use the base classes to refer to the derived classes and no
cast is needed:

void Foo( const Shape& shape )
{
// ...
shape.Draw();
// ...
}

We could pass a Circle or a Square into this function. If we needed to
call Square::Rotate(), we should probably not do so from Foo since
Shape (and its subclass Circle) does not support the Rotate operation.
The design should be altered so that the object we have is guaranteed
to be a Square, e.g.,

void Bar( Square& square )
{
// ...
square.Rotate( 20.5 );
Foo( square );
// ...
}

You might be interested in the FAQ for this group, which as several
sections on inheritance:

http://www.parashift.com/c++-faq-lite/

Cheers! --M
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top