virtual casting

H

Herby

Given class B and C which inherit from class A
They all override a method of the form:
Add( A^ lhs, A^ rhs ); So A is abstract.

So if i was defining Add for class B :


B::Add( A^ lhs, A^ rhs )
{
Value = ((B)lhs)->Value + ((B)rhs)->Value;
}

And the rhs argument happens to be of type C, although mostly it would
be of type B.
Instances of type C can legally be cast( converted ) to instances of
type B.

Given the argument is of type A, and the actual instance can be either
B or C.
How can i cast rhs to B?

I tried adding a virtual and concrete operatorB*() to A and C,
but made no difference?

Any ideas greatly appreciated?
 
J

Jakob Bieling

Herby said:
Given class B and C which inherit from class A
They all override a method of the form:
Add( A^ lhs, A^ rhs ); So A is abstract.

A^? I have seen that in some Microsoft specific CLI code. This is
*not* C++!
So if i was defining Add for class B :


B::Add( A^ lhs, A^ rhs )
{
Value = ((B)lhs)->Value + ((B)rhs)->Value;
}

Why not just pass references to B objects? Then you would not have
to cast here at all.
And the rhs argument happens to be of type C, although mostly it would
be of type B.
Instances of type C can legally be cast( converted ) to instances of
type B.

Then I guess they could be implicitly casted to "references to B".
Considering the above remark, you could pass B and C objects now
Given the argument is of type A, and the actual instance can be either
B or C.
How can i cast rhs to B?

You can't. If all you have is A, then there is no way to pretend it
to be a B.

hth
 
H

Herby

Firstly please substitute ^ for *. Am currently running this problem
against C++\CLI, but is more general to C++.

The problem is the client only has pointers to A*
and it does not know if they are B or C instances..

Ideally i would define

B::Add( B* lhs, C* rhs )
{
// now works
static_cast<B*>(rhs)
// given in class C i have defined operatorB*()
// like a string class converting itself to a double given thats
what it text contains
}

and at runtime given these are the types of the instances, then this
would be the method called.
But its not - its linked to the A* A* method.

I thought it would be possible by defining a virtual cast operator in A
but it is not called? I do not understand why not?

If its really not possible i need this confirmed and then go back to
the drawing board.

Thanks.
 
J

Jakob Bieling

Herby said:
Firstly please substitute ^ for *. Am currently running this problem
against C++\CLI, but is more general to C++.

The problem is the client only has pointers to A*
and it does not know if they are B or C instances..

I do not really know what your inheritance tree looks like, but I am
assuming the following:

class A {};

class B : public A { int Value; };

class C : public B {};
Ideally i would define

B::Add( B* lhs, C* rhs )

Given the above, you can just have:

B* B::Add( B* lhs, B* rhs );

without the need or operator B* ().
{
// now works
static_cast<B*>(rhs)
// given in class C i have defined operatorB*()

'operator B* ()' has nothing to do with this. You are casting the
pointer, and not applying 'operator B*()' to the *object*.
// like a string class converting itself to a double given thats
what it text contains
}

and at runtime given these are the types of the instances, then this
would be the method called.
But its not - its linked to the A* A* method.

Did you make "Add" virtual? Are you calling "Add" on an object of
type A or A? You really need to provide more details. Please post
minimal code that I can compile or at least try to compile so that I get
the error you are getting.
I thought it would be possible by defining a virtual cast operator in
A but it is not called? I do not understand why not?

If its really not possible i need this confirmed and then go back to
the drawing board.

hth
 
B

Bob Hairgrove

Given class B and C which inherit from class A
They all override a method of the form:
Add( A^ lhs, A^ rhs ); So A is abstract.

So if i was defining Add for class B :


B::Add( A^ lhs, A^ rhs )
{
Value = ((B)lhs)->Value + ((B)rhs)->Value;
}

And the rhs argument happens to be of type C, although mostly it would
be of type B.

You left out a very important detail: what is the type of the return
value for Add()? You cannot instantiate an object of type A because A
is abstract. Therefore, you cannot return an object of type A.

However, you cannot return a reference to A because Value is computed
within the function, and you must not return references or pointers to
local objects.

???
 
D

Daniel T.

"Herby said:
Given class B and C which inherit from class A
They all override a method of the form:
Add( A^ lhs, A^ rhs ); So A is abstract.

So if i was defining Add for class B :


B::Add( A^ lhs, A^ rhs )
{
Value = ((B)lhs)->Value + ((B)rhs)->Value;
}

Normally, 'Add' adds two numbers together. However, the function above
takes three parameters (one of which you oddly don't use.) I can't help
wondering why you did that... Is that some special definition in the
language you are using?

If this were written in C++, then I would tell you to either make this a
non-member function or remove one of the parameters.
And the rhs argument happens to be of type C, although mostly it would
be of type B.
Instances of type C can legally be cast( converted ) to instances of
type B.

Then why have type C? Just make everything a B and be done with it.

Given the argument is of type A, and the actual instance can be either
B or C.
How can i cast rhs to B?

You can't. Let me be more clear, you *can* do it (reinterpret_cast)
however doing so is a bad decision.
I tried adding a virtual and concrete operatorB*() to A and C,
but made no difference?

Any ideas greatly appreciated?

Try moving Value into class A and making your Add method global (not a
member-function.)

Of course, my advice only applies to C++, so it may not have any value
to you in the language you are using.
 
H

Herby

Guys thanks for the great response. I have been posting this into the
C++\CLI forum and not getting any replies.
Im a little concerned as it may imply i have still some fundamentals to
understand about casting and virtual functions etc.

So i will now provide you with some minimal classes and share my
problem with you:


class A
{
public:
virtual void Add( A* lhs, A* rhs )=0;
};

---------------------------------------------------------

class B : public A
{
public:

B( String* value){Value = value;};
virtual void Add( A* lhs, A* rhs );

operator C*() { // converts string value to double given it contains
something like "1008.790" :};

String* Value;
};

// Assume here that String comes from common base library could be
CString or std::string etc
-------------------------------------------------------------------

public ref class C : public A
{
public:

C( double value ){ Value = value; };

virtual void Add( A* lhs, A* rhs )
{
Value = static_cast<C*>(lhs)->Value +
static_cast<C*>(rhs)->Value;
// here i assumed the cast operator would be called on rhs -
whereby it would return itself as an object of B*
}

double Value;
};

So Value cannot go into base class as is a different type in all the
subclasses of A.
And C does not inherit from B, is a sibling of C.

Some client code:

int main()
{
C* c = new C(515.18);
B* b = new B("50");

A* lhs = c;
A* rhs = b;

C* c2 = new C(100); // this will recieve the new value

c2->Add(lhs, rhs);

}

So the Add is applied to an object and the value computed is assigned
to this object.
Dont worry about this part of it though.

Just how can i assign a value of C to B, when using a pointer to A ?
More precisly

lhs = (C*)rhs;

Where rhs is currently pointer to A*.

Is this possible - it feels like it should be?
If not why not? why can i not define a virtual cast to C* jn A ?

Thanks.
 
D

Daniel T.

"Herby said:
Guys thanks for the great response. I have been posting this into the
C++\CLI forum and not getting any replies.
Im a little concerned as it may imply i have still some fundamentals to
understand about casting and virtual functions etc.
virtual void C::Add( A* lhs, A* rhs )
{
Value = static_cast<C*>(lhs)->Value +
static_cast<C*>(rhs)->Value;
// here i assumed the cast operator would be called on rhs -
whereby it would return itself as an object of B*
}

Not at all, the casting operator isn't in A. I recommend that you put a
virtual member_function in A that returns the value as a double. Then:

class A {
public:
virtual double DoubleVal() const = 0;
};

double B::DoubleVal() const {
/* convert the string and returns a double */
}

void B::Add( A* lhs, A* rhs ) {
double tmp = lhs->DoubleVal() + rhs->DoubleVal();
/* convert tmp into a string and assign to Value */
}

double C::DoubleVal() const { return Value; }

void C::Add( A* lhs, A* rhs ) {
Value = lhs->DoubleVal() + rhs->DoubleVal();
}

Give up on the casting operator already...
 
H

Herby

Well done Daniel, you have solved my problem.
I knew there was a simple solution to all this. That works well.
Thanks.
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top