 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
J.Beaulieu Guest
|
Posted: Sun Aug 29, 2004 10:47 pm Post subject: dynamic casting |
|
|
Hi,
let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
}
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
I want to instanciate A_1,A_2 or A_3 and to be able, with a 'A'
pointer (base class) to call the correct method. How can I do that? I
know that the void * definition is wrong and there is something bad
about these overload, but the base class must guess on the flye what
get_max method is to be called.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Korotkov Guest
|
Posted: Mon Aug 30, 2004 10:49 am Post subject: Re: dynamic casting |
|
|
| Quote: | let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
}
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
|
You can't compile this. Return types of virtual overrides must be
covariant (for example, A* and A_1*).
--
Ivan
e-mail me at: korotkov2 at ztel dot ru
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Mon Aug 30, 2004 10:54 am Post subject: Re: dynamic casting |
|
|
J.Beaulieu <jfbeaulieu2003 (AT) yahoo (DOT) com> wrote:
| Quote: | Hi,
let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
}
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
I want to instanciate A_1,A_2 or A_3 and to be able, with a 'A'
pointer (base class) to call the correct method. How can I do that? I
know that the void * definition is wrong and there is something bad
about these overload, but the base class must guess on the flye what
get_max method is to be called.
I see you want different return types, if this is correct thwn you |
need to know what you want later, you can put in a discriminated union
of the pointers, see boost::any, boost::variant, or write your own.
struct result
{
enum {DBL,LNG,CHR} which;
union
{
long *lp
double *dp;
char * cp]
};
};
if you now let all the get_max()'s return a result, then testing
result::which will determine which pointer is actually in the union.
You can defer this testing until it is actually going use the result.
void test(A *p)
{
long l;
double d;
char *cp;
result r = p->get_max();
switch(r.which)
{
case result::DBL: d = *r.dp;break;
case result::LNG: l = *r.lp;break;
case result::CHR: cp = r.cp;break;
}
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Sheehan Guest
|
Posted: Mon Aug 30, 2004 10:59 am Post subject: Re: dynamic casting |
|
|
You cannot do exactly what you are trying to. A polymorphic method
chosen at runtime needs to have the same signature (with one
exception, which doesn't apply here), or else the generated assembly
would not work properly. You do have a few options:
1.) Use a void*. This doesn't do you much good, as the calling code
needs to know which derived class it was calling. If it already knows
that, it can just call the correct version without a virutal function.
2.) Have the return type be a discriminating union, such as
boost::any or the one proposed by Alexandrescu.
The bigger question would be why you are trying to do this. My guess
is that there is a better design that you could choose to do what you
are wanting to, without using a virtual function with a morphing
interface. If you post some more information, maybe you can get some
advice about a better approach.
John Sheehan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
llewelly Guest
|
Posted: Mon Aug 30, 2004 11:10 pm Post subject: Re: dynamic casting |
|
|
[email]jfbeaulieu2003 (AT) yahoo (DOT) com[/email] (J.Beaulieu) writes:
| Quote: | Hi,
let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
|
Why do the derived classes' overriders of get_max() need to return
things as different as double* and char* ? In a staticly typed
langauge like C++, the need to do so is usually evidence of poor
design.
There is some potential danger here; you will need some source of
meta-knowledge to determine the proper type to cast your void* to
when it comes time use the data.
If can't or won't reconsider the need to return pointers to different
types from the derived classes, consider some wrappers which
leverage C++'s built-in rtti to retain information about the
proper types of the data:
struct number_wrapper
{
virtual ~number_wrapper();
};
struct double_wrapper:number_wrapper
{
double value;
};
struct long_wrapper:number_wrapper
{
long value;
};
struct char_wrapper:number_wrapper
{
char value;
};
struct A
{
virtual number_wrapper* get_max();
};
struct A_1:A
{
double_wrapper* get_max();
};
void foo(number_wrapper* bar)
{
if(double_wrapper* d= dynamic_cast<double_wrapper*>(bar))
{
double dd= d->value;
//use double value ...
}
}
Alternatively, if you can count on direct access to to the A
instances when you use the data, you can simply take 'get_max()'
out of the base class interface and rely on dynamic_cast
directly:
struct A{virtual ~A();};
struct A_1:A
{
double* get_max();
};
struct A_2:A
{
long* get_max();
};
void foo(A* bar)
{
if(A_1* baz= dynamic_cast<A_1*>(bar))
{
double d= baz->get_max();
// use d ...
}
}
| Quote: | }
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
|
Did you really mean to use private inheritance, and to provide no
public wrappers for your private virtual functions?
| Quote: | I want to instanciate A_1,A_2 or A_3 and to be able, with a 'A'
pointer (base class) to call the correct method.
[snip] |
I think you need to rephrase your question. It's not at all clear to
me what you mean by 'correct'.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Michiel Salters Guest
|
Posted: Tue Aug 31, 2004 12:06 am Post subject: Re: dynamic casting |
|
|
[email]jfbeaulieu2003 (AT) yahoo (DOT) com[/email] (J.Beaulieu) wrote in message news:<eb1b8a74.0408290409.3b7198d6 (AT) posting (DOT) google.com>...
| Quote: | Hi,
let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
}
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
I want to instanciate A_1,A_2 or A_3 and to be able, with a 'A'
pointer (base class) to call the correct method. How can I do that? I
know that the void * definition is wrong and there is something bad
about these overload, but the base class must guess on the flye what
get_max method is to be called.
|
The design is wrong. Let's say I have this use:
A* myA = getSomeA
TYPE t = *(myA->get_max());
C++ is strongly typed, so you must say what TYPE is. If you can't,
get_max() is wrong. The problem is not gussing which get_max is
called, but which type is returned.
Regards,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Nicola Musatti Guest
|
Posted: Tue Aug 31, 2004 12:09 am Post subject: Re: dynamic casting |
|
|
[email]jfbeaulieu2003 (AT) yahoo (DOT) com[/email] (J.Beaulieu) wrote in message news:<eb1b8a74.0408290409.3b7198d6 (AT) posting (DOT) google.com>...
| Quote: | Hi,
let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
}
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
I want to instanciate A_1,A_2 or A_3 and to be able, with a 'A'
pointer (base class) to call the correct method. How can I do that? I
know that the void * definition is wrong and there is something bad
about these overload, but the base class must guess on the flye what
get_max method is to be called.
|
There is something wrong with your logic. Suppose what you wanted was
possible; it would then also be possible to have something like:
void f(A * a) {
??? v = a->get_max();
}
How can you know what should the type of v be? In practice you have
three alternatives:
- Make all the overloads return the same type;
- Wrap the return types in a set of classes with virtual functions, so
as
to be able to use "covarian return types" (i.e. the fact that a
virtual
function in a derived class may return a pointer or reference to a
class
that is derived from the one returned by pointer or reference in the
base class);
- Use distinct overloads or templates.
To be more precise I'd need to know more about your problem.
Cheers,
Nicola Musatti
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Vladislav Lazarenko Guest
|
Posted: Tue Aug 31, 2004 10:01 am Post subject: Re: dynamic casting |
|
|
[email]jfbeaulieu2003 (AT) yahoo (DOT) com[/email] (J.Beaulieu) wrote in message news:<eb1b8a74.0408290409.3b7198d6 (AT) posting (DOT) google.com>...
| Quote: | Hi,
let say that I ant to have these ones:
class A{
virtual void *get_max();
}
class A_1:A {
double *get_max();
}
class A_2:A {
long *get_max();
}
class A_3:A {
char * get_max();
}
I want to instanciate A_1,A_2 or A_3 and to be able, with a 'A'
pointer (base class) to call the correct method. How can I do that? I
know that the void * definition is wrong and there is something bad
about these overload, but the base class must guess on the flye what
get_max method is to be called.
|
Hi, J.Beaulieu.
I don't know the main purpose of the algorithm you creating. For now I
have two proposals.
1) Maybe it is better to use template <typename T> std::max(const T &
lhs, const T & rhs) ? (It is a Standard Template Library compare
algorithm)
2) Use homomorphic hierarchy and double dispatch. For example from
"C++ for real programmers" book:
class Number {
protected:
virtual Number& operator+(const Integer&) = 0;
virtual Number& operator+(const Complet&) = 0;
public:
virtual Number& operator+(const Number&) = 0;
virtual Number& operator-(const Number&) = 0;
// etc...
};
class Integer : public Number {
private:
int I;
protected:
virtual Number& operator+(const Integer&);
virtual Number& operator+(const Complex&);
public:
Integer(int x) : i(x) {}
virtual Number& operator+(const Number&);
// etc...
};
Number& Integer::operator+(const Number& n)
{
return n + *this; // change right-hands operand with left-hands
}
// START OF PSEUDO-CODE ...
Number& Integer::operator+(const Integer& n)
{
if (i + n.i TOO BIG FOR int) {
return COMPLEX etc...
}
else return Integer(i + n.i);
}
// END OF PSEUDO-CODE
Good luck!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
J.Beaulieu Guest
|
Posted: Tue Aug 31, 2004 10:15 am Post subject: Re: dynamic casting |
|
|
Hi, the code would be too long to analyse here, but don't worry I have
the time to redesign it soon if necessary. Thanks to all for the infos
concerning the union.
[email]jsheehan (AT) gmail (DOT) com[/email] (John Sheehan) wrote in message news:<570fbf87.0408292042.737befb1 (AT) posting (DOT) google.com>...
| Quote: | You cannot do exactly what you are trying to. A polymorphic method
chosen at runtime needs to have the same signature (with one
exception, which doesn't apply here), or else the generated assembly
would not work properly. You do have a few options:
1.) Use a void*. This doesn't do you much good, as the calling code
needs to know which derived class it was calling. If it already knows
that, it can just call the correct version without a virutal function.
2.) Have the return type be a discriminating union, such as
boost::any or the one proposed by Alexandrescu.
The bigger question would be why you are trying to do this. My guess
is that there is a better design that you could choose to do what you
are wanting to, without using a virtual function with a morphing
interface. If you post some more information, maybe you can get some
advice about a better approach.
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|