The merits of dynamic_cast<>()

L

Leslaw Bieniasz

Hi,

I am curious what is the current opinion about the merits of using
dynamic_cast<>(). I remember reading somewhere several years ago
that it was considered a bad practice to use the dynamic casting,
and that in cases when such a need arises, one should think about
redesigning the code. My question is how to do it.
The situation that I have is as follows:

I have a base class A, and a number of derived classes B, C, etc.
The problem is that although the classes have a lot of common
functionality (contained in A), there are also some specific
features (new methods) added to B, C, etc.
But, since there is a common functionality, it is convenient to
keep pointers to the various objects as pointers to A, in a common
container. This implies that whenever I need to access the common
functionality, I can use pointers to A, but if I need the specific
features, I have to cast from the pointer to A, to pointers to derived
classes. Is this OK, or there are ways to implement the same
thing without using dynamic_cast<>() ?

Leslaw
 
S

Stuart Redmann

Hi,

I am curious what is the current opinion about the merits of using
dynamic_cast<>(). I remember reading somewhere several years ago
that it was considered a bad practice to use the dynamic casting,
and that in cases when such a need arises, one should think about
redesigning the code. My question is how to do it.
The situation that I have is as follows:

I have a base class A, and a number of derived classes B, C, etc.
The problem is that although the classes have a lot of common
functionality (contained in A), there are also some specific
features (new methods) added to B, C, etc.
But, since there is a common functionality, it is convenient to
keep pointers to the various objects as pointers to A, in a common
container. This implies that whenever I need to access the common
functionality, I can use pointers to A, but if I need the specific
features, I have to cast from the pointer to A, to pointers to derived
classes. Is this OK, or there are ways to implement the same
thing without using dynamic_cast<>() ?

I'd advise to use several containers for the derived class pointers:
one container contains all objects with their base interface A, one
contains pointers to all B objects, and one contains all objects of
type C. This means that registering objects of type B includes
registering the object in the list of As as well. This makes the code
much more readable and maintainable than using dynamic_casts, IMHO.

Regards,
Stuart
 
S

Sudarshan Narasimhan

Define all methods as virtual methods in your base class, with the base
class's skeleton implementation returning an appropriate error code, or
throwing an appropriate exception, then define the appropriate methods in
each one of your derived classes.

Although this is not the case where one would use dynamic_cast<>, there's
nothing wrong, per se, with this operator.

 application_pgp-signature_part
< 1KViewDownload


What you have described is a very common situation.

If derived classes have new functionality which is not related to the
base class, then it is a violation of the public inheritance "is a"
paradigm. If a set of derived classes alone implement this new
functionality, then it makes sense to have a new class derive from A
(which defines a virtual method that such sub classes need to
implement) and the classes implementing this functionality derive from
this new class. It makes the design that much cleaner.

I can provide an example.

class Mammals {

virtual move();
virtual eat();
virtual breed();

string name;
}; // Fine for humans, cows and goats

How about the mammals dolphins, whales. A swim method needs to be
defined for them. So if there were a function that calls this method,

void swim(Mammals &m)
{
// Need a dynamic cast here
m->swim(); // You need a dynamic cast here if you are passing a
"Mammal"
}

solution:

class AquaticMammals : public Mammals {

virtual void swim(); //
}

class dolphin: public AquaticMammals {

};

Now you can pass AquaticMammals without using a dynamic cast.

void swim(AquaticMammals &m)
{
m->swim(); // No need for a cast, also it realistically represent
the relationship
}

You can check if this helps.

If you cannot for some reason redefine the classes, add these new
functionalities as virtual methods in the base class, provide a
default implementation to throw an error(catch it at run time to see
any calls to inappropriate derived classes). Only in the required
classes, redefine these functions to provide desired implementation.
However, approach 1 is desirable.
 
S

Sudarshan Narasimhan

What you have described is a very common situation.

If derived classes have new functionality which is not related to the
base class, then it is a violation of the public inheritance "is a"
paradigm. If a set of derived classes alone implement this new
functionality, then it makes sense to have a new class derive from A
(which defines a virtual method that such sub classes need to
implement) and the classes implementing this functionality derive from
this new class. It makes the design that much cleaner.

I can provide an example.

class Mammals {

    virtual move();
    virtual eat();
    virtual breed();

    string name;

}; // Fine for humans, cows and goats

How about the mammals dolphins, whales. A swim method needs to be
defined for them. So if there were a function that calls this method,

void swim(Mammals &m)
{
    // Need a dynamic cast here
    m->swim(); // You need a dynamic cast here if you are passing a
"Mammal"

}

solution:

class AquaticMammals : public Mammals {

    virtual void swim();  //

}

class dolphin: public AquaticMammals {

};

Now you can pass AquaticMammals without using a dynamic cast.

void swim(AquaticMammals &m)
{
    m->swim();  // No need for a cast, also it realistically represent
the relationship

}

You can check if this helps.

If you cannot for some reason redefine the classes, add these new
functionalities as virtual methods in the base class, provide a
default implementation to throw an error(catch it at run time to see
any calls to inappropriate derived classes). Only in the required
classes, redefine these functions to provide desired implementation.
However, approach 1 is desirable.


Also i would add that if you need to pass a base type to call a "new
functionality" added to a "few" derived classes, it is not really
correct to pass a base type in the first place. You need a subtype as
indicated. But if all your derived classes need to implement this
functionality, make it (pure)virtual in the base class and redefine in
all the derived clasees. IN either case you dont need a dynamic_cast.

And cases where you cannot perhaps avoid a dynamic_cast<> are: if you
need to implement a handler which receives a message; it could be any
type of msg, all you know is it is of a base type "class Msg". And if
you have to do different things for different types of messages(again
this indicates a missing design consideration but lets just say you
cant change the Msg related code); you got to use dynamic_cast<>. But
its really great if you can restrict the usage of dynamic_cast<> to
just that.
 
N

Nick Keighley

I am curious what is the current opinion about the merits of using
dynamic_cast<>(). I remember reading somewhere several years ago
that it was considered a bad practice to use the dynamic casting,
and that in cases when such a need arises, one should think about
redesigning the code. My question is how to do it.
The situation that I have is as follows:

I have a base class A, and a number of derived classes B, C, etc.
The problem is that although the classes have a lot of common
functionality (contained in A), there are also some specific
features (new methods) added to B, C, etc.

could you give a more concrete example?
But, since there is a common functionality, it is convenient to
keep pointers to the various objects as pointers to A, in a common
container.

why a common container? What is it that unites them and what is it
that distinguises them?

This implies that whenever I need to access the common
functionality, I can use pointers to A, but if I need the specific
features, I have to cast from the pointer to A, to pointers to derived
classes. Is this OK, or there are ways to implement the same
thing without using dynamic_cast<>() ?

whya re B's and C's mixed together if they aren't the same
base class? I supose you might want to save everything to
a database but doing different operation on different things
in the same code seems odd.

Container<BaseObject*> container;

for (i = container::begin(); i != container::end(); ++i)
{
BaseObject* obj = *i;
Spaceship* spaceShip;
Marrow* marrow;

if ((spaceShip = dynamic_cast<Spaceship*>(obj)) != 0)
spaceShip->launch();
else
if ((marrow = dynamic_cast<Marrow*>(obj)) != 0)
marrow->grow();

etc.
}

There ought to be *some* connection between them
 
N

Noah Roberts

Sam said:
Define all methods as virtual methods in your base class, with the base
class's skeleton implementation returning an appropriate error code, or
throwing an appropriate exception, then define the appropriate methods
in each one of your derived classes.

This is really poor design and extremely BAD advice. I've certainly
seen it a lot and produced by a lot of self-declared experts, even
people who have been coding for years. However, it breaks every
principle there is and thus inevitably leads to problems.

The problem here is that class B "is not" a class A and you are forcing
that relationship.
 
N

Noah Roberts

Leslaw said:
Hi,

I am curious what is the current opinion about the merits of using
dynamic_cast<>(). I remember reading somewhere several years ago
that it was considered a bad practice to use the dynamic casting,
and that in cases when such a need arises, one should think about
redesigning the code. My question is how to do it.

You should certainly question any design that is full of dynamic_cast
code. However, you might look into ways of limiting such casting to
particular modules or concepts in your code by using the visitor
pattern. There's a really good one described in _Modern_C++_.
 
A

Andreas Dehmel

[...]
But, since there is a common functionality, it is convenient to
keep pointers to the various objects as pointers to A, in a common
container. This implies that whenever I need to access the common
functionality, I can use pointers to A, but if I need the specific
features, I have to cast from the pointer to A, to pointers to derived
classes. Is this OK, or there are ways to implement the same
thing without using dynamic_cast<>() ?

I'd advise to use several containers for the derived class pointers:
one container contains all objects with their base interface A, one
contains pointers to all B objects, and one contains all objects of
type C. This means that registering objects of type B includes
registering the object in the list of As as well. This makes the code
much more readable and maintainable than using dynamic_casts, IMHO.


Try doing that with e.g. a drawing program where all sorts of different
objects have to be processed in arbitrarily interleaved order and
give us a call if you've survived basic editing facilities without
going insane; and then there's years of maintenance which'll definitely
finish the job... You'd need an awful lot of dynamic casts for this to
be more readable in situations like this. This approach may work for some
specific problems, but as a general design advice it's just as poor as
bloating the base interface with virtual functions for all eventualities.

Ultimately, it's dogmatism like ``never use X'' (dynamic casts,
preprocessor, ...) which leads to _really_ bad code. If you need
dynamic casts half the time you're accessing your objects it's
definitely bad design, but a reasonable amount of them is perfectly
alright.



Andreas
 
J

Joshua Maurice

Hi,

I am curious what is the current opinion about the merits of using
dynamic_cast<>(). I remember reading somewhere several years ago
that it was considered a bad practice to use the dynamic casting,
and that in cases when such a need arises, one should think about
redesigning the code.

Specifically, it's not only dynamic_cast which is considered bad
practice. Usually, every cast of every kind is assumed bad until
proven good. Good C++ code should contain (near) 0 explicit casts of
any kind. Explicit casting has been known to lead to problem.

This is the idealized version. Maybe your problem is better solved
with a cast here or there. Maybe you're using a dynamic_cast in an
assert to assert the correct dynamic type of an object. Maybe you're
forced to use a badly written C++ library and that forces you to use
explicit casts. Maybe you have a C library which forces you to use
explicit casts. Etc. Generally, it is accepted that for large
products, type safety is your friend. A lot of people on here would
not even consider writing a large product without string type safety.
Every single cast is a hole in that type safety net.

Ex: I just rewrote a large portion of (gnu) make for fun, and I have
exactly 3 explicit casts in the 6600 lines of source. One static_cast
required to use the threading libraries of POSIX and WIN32. 2 more
static_casts to quiet compiler warnings about an unsigned to signed
copmarison and to quiet compiler warnings about assigning an integral
type to a potentially smaller integral type (streamsize and size_t).
 
J

Joshua Maurice

Can you define a couple of these alleged principles, if you don't mind.


Nobody said that class B is class A. Class B is derived from class A.

See the circle and ellipse problem.
http://en.wikipedia.org/wiki/Circle-ellipse_problem

He was using what's commonly known as the Liskov Substitution
Principle (LSP), that a derived type should "be a" valid object of the
base type. The exact interpretation of LSP differs. The useful
interpretation IMHO is: the base class has a certain contract it
claims to follow. All subtypes should obey that contract.
(Inheritance, aka derived types, is one way to create a subtype
relationship.) Each object of a subtype has different behavior than
the base type and other subtypes, otherwise they're just synonyms for
the same thing, but to truly be a "subtype", they must still obey the
contract of the base class. That is LSP.

A simple example would be the Java collections framework. In C++, it
would have an abstract base class Map. It has two derived concrete
classes, HashMap and TreeMap. Map supports iteration, insertion, and
removal of elements. Map has the contract that if you insert a unique
element, then iteration over the map will return that element exactly
one, and the other usual semantics. HashMap and TreeMap fully conform
to this contract. Thus, whereever a Map is required, one can use a
HashMap or a TreeMap. A HashMap "is a" Map, and a TreeMap "is a" Map.
LSP. However, a TreeMap further refines the contract of iteration. It
will iterate over the elements in sorted order, whereas HashMap
iterates over elements in an 'arbitrary' order. TreeMap and HashMap
have different semantics for iteration, but both conform to the
contract of Map, aka both are subtypes (as defined by my particular
interpretation of LSP).

Sam, your suggestion is similar to several common anti-patterns, such
as the god object
http://www.c2.com/cgi/wiki?GodObject

By having each virtual function throw an "unsupported exception" by
default, and derived types implement some of them, you do not
establish actual "subtypes", only "derived types". The derived types
do not obey LSP (or they do trivially because your base class has no
contract, and thus is unusable). It is generally recognized that
pretending you have LSP subtypes when you do not is a source of bad
code.

In the OP's example, he has a bunch of concrete types B, C, ..., and
an abstract base type A. He finds that he frequently needs to
dynamic_cast from A* to derived* to do operations specific to a
derived type. Again, this is generally recognized as a failure to
properly define subtypes, and is generally recognized to lead to "bad"
code. There is no silver bullet answer. You need to sit down with the
specific problem in hand and define useful abstractions. No one here
can really reliably answer how you should define your abstractions
without knowing your problem and its domain.
 
J

Joshua Maurice

See the circle and ellipse problem.http://en.wikipedia.org/wiki/Circle-ellipse_problem

He was using what's commonly known as the Liskov Substitution
Principle (LSP), that a derived type should "be a" valid object of the
base type. The exact interpretation of LSP differs. The useful
interpretation IMHO is: the base class has a certain contract it
claims to follow. All subtypes should obey that contract.
(Inheritance, aka derived types, is one way to create a subtype
relationship.) Each object of a subtype has different behavior than
the base type and other subtypes, otherwise they're just synonyms for
the same thing, but to truly be a "subtype", they must still obey the
contract of the base class. That is LSP.

A simple example would be the Java collections framework. In C++, it
would have an abstract base class Map. It has two derived concrete
classes, HashMap and TreeMap. Map supports iteration, insertion, and
removal of elements. Map has the contract that if you insert a unique
element, then iteration over the map will return that element exactly
one, and the other usual semantics. HashMap and TreeMap fully conform
to this contract. Thus, whereever a Map is required, one can use a
HashMap or a TreeMap. A HashMap "is a" Map, and a TreeMap "is a" Map.
LSP. However, a TreeMap further refines the contract of iteration. It
will iterate over the elements in sorted order, whereas HashMap
iterates over elements in an 'arbitrary' order. TreeMap and HashMap
have different semantics for iteration, but both conform to the
contract of Map, aka both are subtypes (as defined by my particular
interpretation of LSP).

Sam, your suggestion is similar to several common anti-patterns, such
as the god objecthttp://www.c2.com/cgi/wiki?GodObject

By having each virtual function throw an "unsupported exception" by
default, and derived types implement some of them, you do not
establish actual "subtypes", only "derived types". The derived types
do not obey LSP (or they do trivially because your base class has no
contract, and thus is unusable). It is generally recognized that
pretending you have LSP subtypes when you do not is a source of bad
code.

In the OP's example, he has a bunch of concrete types B, C, ..., and
an abstract base type A. He finds that he frequently needs to
dynamic_cast from A* to derived* to do operations specific to a
derived type. Again, this is generally recognized as a failure to
properly define subtypes, and is generally recognized to lead to "bad"
code. There is no silver bullet answer. You need to sit down with the
specific problem in hand and define useful abstractions. No one here
can really reliably answer how you should define your abstractions
without knowing your problem and its domain.

Err, here is a slightly more useful link for God Object
http://en.wikipedia.org/wiki/God_object
 
J

Joshua Maurice

You are redefining the OP's question. The OP wants to eliminate a bunch of
messy dynamic_cast<>s. That's all. The OP was not explicitly interested in
some theoretically pure solution, just a better way of doing things.

Contrary to popular belief, academics is not entirely worthless when
solving real world problems.
Well,
here's a better way of doing things. Whether this solution meets the
requirements of some theoretically perfect academic principle is outside the
scope.

What solution?
I just can't quite understand the notion that, well, since no ultimately
perfect solution is possible, supposedly, then you'll just have to be
content with flinging dynamic_cast<>s all over the place. Because that's
what this says.

What says that? What?

My entire post was prompted from:

Nobody said that class B is class A. Class B is derived from class A.

Sam, you do not apparently know or understand LSP. I attempted to
rectify that. Moreover, my main point is that: it is generally
accepted that, "in the real world", attempting to force subtyping when
the types are not actual subtypes (as defined by LSP) leads to bad
code. This is what Noah Roberts said succinctly here:

Noah said:
The problem here is that class B "is not" a class A and you are forcing
that relationship.

Continuing on with your post:

Furthermore, who's to say that the base's class "contract" is that all of
its methods must be implemented, and none of them may throw an exception?
Who said that? I don't see anyone saying that. That's just an arbitrary
contract that's gratuitously imposed on the base class. But who's to say
that the base class's contract is not: method X returns an enumerate value
that defines which other methods are defined for the given instance of the
base class, and all others throw an exception.

Perhaps you could respond to what I already said on this topic:

By having each virtual function throw an "unsupported exception" by
default, and derived types implement some of them, you do not
establish actual "subtypes", only "derived types". The derived types
do not obey LSP (or they do trivially because your base class has no
contract, and thus is unusable). It is generally recognized that
pretending you have LSP subtypes when you do not is a source of bad
code.

To elaborate, you have a continuum of choices. At one end, your base
class can give no guarantee at all on what happens when you its
functions. Such a base class is inherently unusable because you can't
do anything reliably to objects of that type (or subtype). The
opposite end of the continuum is the base class is a concrete class
with fully specified behavior. Abstraction is about finding that happy
middle ground with some specification, and some "implementation
defined". Such a middle ground is inherently specific to the problem
domain.

It is my belief, and that of others in this thread, that having a base
class throw "unsupported exception" by default is too close to the one
end of the continuum of not giving enough weight to the contract. It's
a code smell, a sign of bad design. Preferably, most functions in an
abstract base class would require the derived type to override it and
fulfill the base class's contract, to give some substance to the base
class's contract, but perhaps some can throw "unsupported exception".
(As to whether allowing some functions to throw "unsupported
exception" is a good idea, I don't know. It's kind of outside the
scope of my main thrust of my argument, nor am I exactly sure how I
feel. I'll stick with "it depends on the problem domain" for now.)

Continuing on with your post:

It's all in the question of how to define the base class's contract.

Agreed.
 
J

Joshua Maurice

I did not state that, of course. I only stated that always having an
academically perfect solution is not a requirement. That's not the same
thing.



The one that I outlined.



Whoever claims that just because this appraach does not fit the mold of an
ultimately perfectly ideal of a base class, that always satisfies some vague
contract, it must be rejected for that reason alone.







Just some of those others. Not everybody.


So? Just because this does not fit some utopian design goal, it must be the
wrong approach? Despite the fact that we don't know the practical details of
the OP's original situation -- nothing more than a general description.


Right. It makes more sense for each derived class to explicitly code for it,
rather than have the default behavior defined by the base class, in one
place.

It makes perfect sense: let's duplicate a whole bunch of code across many
classes, instead of providing a default implementation. All in the name of
fullfilling an idealistic design goal.

I do not see that the whole reason for a base class's existence is to
provide some kind of a contract. A mandate. This may be the premise for some
academic design goal. However, nothing states that this design goal must
always be used, in practice.

In a class hierarchy, a base class provides nothing more than a defined API.
The derived class implements the API. Different derived classes provide
different implementation of the same API, with different semantics.

You misunderstand me.

My complaint is not with forcing the derived class writers to
duplicate the code. If you have the base class contract be "each of
these functions may throw 'unsupported exception'", then I fully agree
it makes sense and is good practice to make the abstract base class
implementation of each function throw "unsupported exception".

My complaint is that it's a bad idea to have such a base class
contract. Generally speaking, it's probably a bad abstraction if
implementers of the abstraction can throw "unsupported exception" for
every function in the abstraction. I'd strongly suggest instead making
your abstraction be applicable to most / all of the derived types, aka
to establish useful LSP subtypes.
 
S

Stuart Redmann

[snipped original post about usage of dynamic_casts]


Andreas said:
Try doing that with e.g. a drawing program where all sorts of different
objects have to be processed in arbitrarily interleaved order

I don't quire get what you mean by "arbitrarily interleaved order"?
[OT: Könnten Sie mir das bitte mal auf Deutsch erklären?]
and
give us a call if you've survived basic editing facilities without
going insane; and then there's years of maintenance which'll definitely
finish the job... You'd need an awful lot of dynamic casts for this to
be more readable in situations like this. This approach may work for some
specific problems, but as a general design advice it's just as poor as
bloating the base interface with virtual functions for all eventualities.

I don't understand why the problem space, drawing programs, should be
prone to dynamic_casts. Could you please elaborate what technical/
maintainance reason there is why we have to use dynamic_casts in
drawing programs? I'd really be interested.
Ultimately, it's dogmatism like ``never use X'' (dynamic casts,
preprocessor, ...) which leads to _really_ bad code. If you need
dynamic casts half the time you're accessing your objects it's
definitely bad design, but a reasonable amount of them is perfectly
alright.

Agreed. To much dogmatism is bad. However, I can only imaging one
reason why dynamic_cast should be preferred over the multiple-
container solution: If your application contains a real _huge_ number
of very small objects, the cost of having to keep additional
containers for specific objects may consume too much memory. May this
be the reason you had originally in mind?

Regards,
Stuart (from Jena)
 
J

James Kanze

This is really poor design and extremely BAD advice. I've
certainly seen it a lot and produced by a lot of self-declared
experts, even people who have been coding for years. However,
it breaks every principle there is and thus inevitably leads
to problems.

I'm not sure I'd agree with the "extremely", but I would argue
that you have to define clear interfaces, implemented by all of
the derived classes. There are a few special cases where one
might reasonably declare "conditionally implemented" functions
in an interfaces, but they certainly aren't common. (The most
frequent case is where a function is only authorised in certain
states, resulting from previous function calls, and some derived
class, for whatever reason, can simply never reach those
states.)
The problem here is that class B "is not" a class A and you
are forcing that relationship.

That's not true. His problem is that class B is not just a
class A; it's a class A and something more. That, in itself,
frequently occurs, even in the best designs. There's certainly
nothing wrong per se with a concrete class implementing several
different interfaces.

If there is a design problem, it's with the code using class A;
there are definite and clear exceptions, but most of the time,
if the code expects a pointer or a reference to an A, then it
should use the interface defined by A. In the exceptional
cases, a dynamic_cast can be used to ask if the object supports
the specific interface or not.

Note that I would be very leary of concrete classes adding
public functions in such a situation. You define an additional
interface (contract), and some of the derived classes implement
it, others not. Also, the number of such interfaces should be
fairly small---if every single derived class implements (or
defines) a new extention to the interface, there's definitely
something wrong somewhere.

One other valid use of dynamic_cast (although it doesn't seem to
be the case here) is in cases of type erasure. Intermediate
entities such as various middleware or persistancy generally
only require a very minimal interface; when recuperating an
object from them, some sort of dynamic_cast is often reasonable
in order to restore the correct type.
 
J

James Kanze

Specifically, it's not only dynamic_cast which is considered
bad practice. Usually, every cast of every kind is assumed bad
until proven good. Good C++ code should contain (near) 0
explicit casts of any kind. Explicit casting has been known to
lead to problem.

Yes and no.

First, any explicit creation of a temporary (i.e. "MyType(
params )") is formally a cast, according to the standard. I
don't think most programmers think of it as one, however (I
certainly don't), and that's probably not what you meant.

Secondly, coercing concrete types into another concrete type is
fully legitimate, if the concrete types represent more or less
the same sort of information: I'd certainly not object to things
like:
std::cout << static_cast< double >( count ) * 100 / max << '%' ;
(Usually, I'll avoid the explicit cast by multiplying by 100.0,
but I wonder if this isn't a bit of obfuscation; it certainly
seems clearer with the explicit conversion.)

Even when talking about dynamic_cast, there are at least two
cases where it would be valid: if the object has transited by
some intermediate code which erases the type (because it handles
many different types), or if the object may (or may not) support
some sort of extended interface.

Casts typically aren't that frequent (with perhaps the exception
of numeric types), but they aren't in themselves necessarily a
sign of poor programming or poor design. It all depends on the
use. (A string of "if (dynamic_cast< A* >( ptr ) ) ... else if
(dynamic_cast< B* >( ptr ) ) ..." is a sign of a problem.)
 
J

joseph cook

Secondly, coercing concrete types into another concrete type is
fully legitimate, if the concrete types represent more or less
the same sort of information: I'd certainly not object to things
like:
    std::cout << static_cast< double >( count ) * 100 / max << '%' ;
(Usually, I'll avoid the explicit cast by multiplying by 100.0,
but I wonder if this isn't a bit of obfuscation; it certainly
seems clearer with the explicit conversion.)

James,
Why not:
std::cout<< double(count) * 100 / max << '%' ;

and save some typing ?

Joe Cook
 
J

Juha Nieminen

James said:
Secondly, coercing concrete types into another concrete type is
fully legitimate, if the concrete types represent more or less
the same sort of information: I'd certainly not object to things
like:
std::cout << static_cast< double >( count ) * 100 / max << '%' ;
(Usually, I'll avoid the explicit cast by multiplying by 100.0,
but I wonder if this isn't a bit of obfuscation; it certainly
seems clearer with the explicit conversion.)

If all the involved operands are (integral) variables and there are no
literals, then an explicit cast is actually the only possible way of
telling the compiler to perform the operation with floating point rather
than integers.

(Ok, you could use an auxiliary variable like "double countF = count;"
and then use that in the expression, but that feels like artificially
trying to avoid the explicit cast for no good reason.)
 
J

Juha Nieminen

Leslaw said:
I am curious what is the current opinion about the merits of using
dynamic_cast<>().

Note that dynamic_cast is more than just "a static_cast with a runtime
check that it succeeds". There are situations where a static_cast can
*not* be used to cast from one type to another, while dynamic_cast can.
(In other words, if you try to use static_cast, you get a compiler
error, while a dynamic_cast will compile and work just ok.)

Not that this situation is very usual, mind.
 
N

Noah Roberts

Sam said:
You are redefining the OP's question. The OP wants to eliminate a bunch
of messy dynamic_cast<>s. That's all. The OP was not explicitly
interested in some theoretically pure solution, just a better way of
doing things. Well, here's a better way of doing things.

Where? The solution you propose is worse. Where's the better one?
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top