Casting from base to derived class

J

James Brown

I have two classes, a base class, and a

class base
{
public:
base();
virtual void foo() = 0;
};

class derived : public base
{
public:
derived();
void foo();
void foo2();
};

Due to existing design, I also have a function which basically does:

base *create_object()
{
return new derived; // Q1. Do I need a cast here?
}

i.e.
base *object = create_object();

Now, I have a requirement to call a non-virtual function in the derived
class,
even though I have a pointer to the case class:

i.e.
derived *object2 = static_cast<derived *>object;
object2->foo2();

So my two questions:

1. In the create_object function, do I need a cast to "downcast" from
derived -> base?

2. Assuming that I can guarantee that create_object *always* returns a
"derived" object
(even though it returns a pointer-to-base), is it safe to cast back to
the derived class?

p.s. I want to avoid using dynamic_cast due to runtime requirements.

So basically I need to know if:

base = derived;
derived = base;

is a safe operation?

TIA
James
 
J

JKop

James Brown posted:
I have two classes, a base class, and a

class base
{
public:
base();
virtual void foo() = 0;
};

class derived : public base
{
public:
derived();
void foo();
void foo2();
};

Due to existing design, I also have a function which basically does:

base *create_object()
{
return new derived; // Q1. Do I need a cast here?
}


No you don't, it's an implicit cast. Just compile it and see!
i.e.
base *object = create_object();

Now, I have a requirement to call a non-virtual function in the derived
class,
even though I have a pointer to the case class:

i.e.
derived *object2 = static_cast<derived *>object;
object2->foo2();

So my two questions:

1. In the create_object function, do I need a cast to "downcast" from
derived -> base?

No.

Consider that your base class is a "Mammal", and that your derived class is
a "Dog". A certain function wants a "Mammal", but you're supplying it with a
"Dog"... but that's okay, because a "Dog" is a "Mammal". You don't have to
put in anything like:

(Mammal*)pDogObject;

It's called an implicit conversion, ie. you're not explicitly specifiying
that it has to be cast, but the compiler knows what to do.

But don't take my word for it, try compile it!
2. Assuming that I can guarantee that create_object *always* returns a
"derived" object
(even though it returns a pointer-to-base), is it safe to cast back to
the derived class?

Absolutley Yes. Given your guarantee that is. Otherwise, Absolutely No.
p.s. I want to avoid using dynamic_cast due to runtime requirements.

Again, given your guarantee, there's no need for a dynamic_cast, static_cast
will suffice and is more efficent, even though the compiler may optimize a
dynamic_cast down to a static_cast.
So basically I need to know if:

base = derived;


Safe in all circumstances, because a Dog is a Mammal.

derived = base;

Here's it's asking for a Dog, but you're just giving it any old Mammal. This
won't even compile. If you want to force it:

derived = static_cast<derived>(base);

But again, I'm only suggesting this given your above guarantee!


(You might want to wait for confirmation on whether static_cast is
appropriate here. I've read loads of articles on the casts but still don't
understand them fully.)


-JKop
 
A

Andre Kostur

JKop said:
James Brown posted:

No.

Minor amendment... going from derived -> base is generally called
"upcasting"... you're going up the inheritance tree...
Absolutley Yes. Given your guarantee that is. Otherwise, Absolutely
No.

Amendment (it's not an absolutely no....). Using dynamic_cast, you can
attempt to downcast to derived to see whether it is a derived object or
not. However, this is not encouraged, but one should try to figure out
some way to implement what you're trying to accomplish via virtual
functions so that you don't need to know whether it's a base or derived
object...
Again, given your guarantee, there's no need for a dynamic_cast,
static_cast will suffice and is more efficent, even though the
compiler may optimize a dynamic_cast down to a static_cast.

Agreed. If you _know_ that the pointer is actually referring to a
derived object, it's safe to static_cast it.
(You might want to wait for confirmation on whether static_cast is
appropriate here. I've read loads of articles on the casts but still
don't understand them fully.)

static is the one you want. reinterpret is a really large sledgehammer,
and tells the compiler to pretty much ignore anything related to type
safety for this cast.
 
C

Chris Theis

"James Brown" <remove_james_dot_brown7_at_virgin_dot_net> wrote in message
[SNIP]
So my two questions:

1. In the create_object function, do I need a cast to "downcast" from
derived -> base?

2. Assuming that I can guarantee that create_object *always* returns a
"derived" object
(even though it returns a pointer-to-base), is it safe to cast back to
the derived class?

p.s. I want to avoid using dynamic_cast due to runtime requirements.

There is a feature called "covariant return types" that in principle solves
your problem of casting. The return type of an overriding function is
required to be either identical to the return type of the overridden
function or "covariant". I´ll spare you the exact definition of covariant
but in short it means that the overriding function of the derived object can
return a pointer to the derived class whereas the overridden function
returns a pointer to the base class. Consequently you can safe yourself the
trouble of having to cast the return type.

For example

class CBase {
public:
CBase* Clone() { return new CBase( *this ); };

virtual void foo();
};

class CDerived : public CBase{
public:
CDerived* Clone() { return new CDerived( *this); };

virtual void foo();
void foo2();
};

CDerived Obj1;
CDerived* pObj = Obj1.Clone();
pObj->foo2(); // no need for a cast
because of the covariant return type CDerived* of the clone function.


HTH
Chris
 
J

John Harrison

Minor amendment... going from derived -> base is generally called
"upcasting"... you're going up the inheritance tree...

Of course this is a magic computer science tree whose roots are at the top
and leaves at the bottom because it grows down the page.

john
 
J

James Brown

John Harrison said:
Of course this is a magic computer science tree whose roots are at the top
and leaves at the bottom because it grows down the page.

john

Thanks for the answers everyone, you've cleared it up nicely for me --


James
 
J

Jack Klein

James Brown posted:



No you don't, it's an implicit cast. Just compile it and see!

There is no such thing as an 'implicit cast' in C++, or in C from
which C++ inherited the concept of casting.

C and C++ can perform conversions between different types of objects.
Some conversions are preformed automatically with no conversion
require, as in:

char ch = 'c';
int i = ch; // automatic conversion of char to int

Other conversions cannot be performed automatically, but may be with
an appropriate cast operator requesting that the specific conversion
be performed.

So a cast is an explicit request for a conversion, which might or
might not have been performed automatically without the cast operator.
 
J

JKop

Jack Klein posted:

There is no such thing as an 'implicit cast' in C++, or in C from
which C++ inherited the concept of casting.

C and C++ can perform conversions between different types of objects.
Some conversions are preformed automatically with no conversion
require, as in:

char ch = 'c';
int i = ch; // automatic conversion of char to int

Other conversions cannot be performed automatically, but may be with
an appropriate cast operator requesting that the specific conversion
be performed.

So a cast is an explicit request for a conversion, which might or
might not have been performed automatically without the cast operator.


Okay, if you want to use your lanugage, an implicit request for a
conversion.

-JKop
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top