need help with casting operators...

J

JustSomeGuy

I have two object types ClassA and ClassB

class ClassA {
public:
int data;
operator ClassB()
{
ClassB b;
b.data = data + 1;
return (b);
}
};

class ClassB {
public:
int data;
operator ClassA()
{
ClassB b;
b.data = data - 1;
return(b);
}
}

So... If I say:

ClassA a1, a2;
ClassB b;

a1.data = 5;
b = a1;
a2 = b;

then a2 should be identical to a1 and b should be 6.

First off I can't get this to compile because ClassB isn't know ClassA
at compile time...

Is it necesary to have int data in both classes or can A inherit from B
and vise versa?

Can both the casting operators exist in only on of the classes?

I guess this is very similar to:

float a1, a2;
int b;
a1 = 5.0
b = a1;
a2 = b;

Of course there is a loss of percision in this case.. but the casting
operations work...

help?
TIA
 
P

Petec

JustSomeGuy said:
I have two object types ClassA and ClassB
First off I can't get this to compile because ClassB isn't know ClassA
at compile time...

Is it necesary to have int data in both classes or can A inherit from
B and vise versa?

Can both the casting operators exist in only on of the classes?
<snip>

I fixed a few logic errors also (ClassB's operator ClassA returned a
ClassB):

class ClassB;

class ClassA {
public:
int data;
operator ClassB();
};

class ClassB {
public:
int data;
operator ClassA();
};

ClassA::eek:perator ClassB()
{
ClassB b;
b.data = data + 1;
return (b);
}

ClassB::eek:perator ClassA()
{
ClassA a;
a.data = data - 1;
return(a);
}

int main()
{
ClassA a1, a2;
ClassB b;

a1.data = 5;
std::cout << "a1.data == " << a1.data << std::endl;

b = a1;
std::cout << "b.data == " << b.data << std::endl;

a2 = b;
std::cout << "a2.data == " << a2.data << std::endl;

return 0;
}

- Pete
 
V

Victor Bazarov

JustSomeGuy said:
I have two object types ClassA and ClassB

class ClassA {
public:
int data;
operator ClassB()
{
ClassB b;
b.data = data + 1;
return (b);
}
};

class ClassB {
public:
int data;
operator ClassA()
{
ClassB b;
b.data = data - 1;
return(b);

You probably meant

ClassA a;
a.data = data - 1;
return a;

}
}
;


So... If I say:

ClassA a1, a2;
ClassB b;

a1.data = 5;
b = a1;
a2 = b;

then a2 should be identical to a1 and b should be 6.

First off I can't get this to compile because ClassB isn't know ClassA
at compile time...

Yes, that's where you need to separate class definitions and member
function definitions:

struct B;
struct A {
int data;
operator B() const;
};
struct B {
int data;
operator A() const;
};
A::eek:perator B() const
{
...
}
B::eek:perator A() const
{
...
}
Is it necesary to have int data in both classes or can A inherit from B
and vise versa?

Inherit? Depends on your model.
Can both the casting operators exist in only on of the classes?
No.


I guess this is very similar to:

float a1, a2;
int b;
a1 = 5.0
b = a1;
a2 = b;

Of course there is a loss of percision in this case.. but the casting
operations work...

It's because the conversion operators are known to the language.

Victor
 
M

Mike Wahler

JustSomeGuy said:
I have two object types ClassA and ClassB

class ClassA {
public:
int data;
operator ClassB()
{
ClassB b;
b.data = data + 1;
return (b);
}
};

class ClassB {
public:
int data;
operator ClassA()
{
ClassB b;
b.data = data - 1;
return(b);
}
}

So... If I say:

ClassA a1, a2;
ClassB b;

a1.data = 5;
b = a1;
a2 = b;

then a2 should be identical to a1 and b should be 6.

First off I can't get this to compile because ClassB isn't know ClassA
at compile time...

Is it necesary to have int data in both classes or can A inherit from B
and vise versa?

Can both the casting operators exist in only on of the classes?

I guess this is very similar to:

float a1, a2;
int b;
a1 = 5.0
b = a1;
a2 = b;

Of course there is a loss of percision in this case.. but the casting
operations work...

#include <iostream>
#include <ostream>

class B;

class A
{
int data;

public:
A(int d = 0) : data (d) { }
operator B() const;
friend std::eek:stream& operator<<(std::eek:stream& os, const A& a)
{
return os << a.data;
}
};

class B
{
int data;

public:
B(int d = 0) : data (d) { }

operator A() const { return data - 1; }
friend std::eek:stream& operator<<(std::eek:stream& os, const B& b)
{
return os << b.data;
}
};

A::eek:perator B() const { return data + 1; }

int main()
{
A a1(5);
A a2;
B b;

b = a1;
a2 = b;

std::cout << "a1 == " << a1 << '\n'
<< "a2 == " << a2 << '\n'
<< "b == " << b << '\n';

return 0;
}

Output:

a1 == 5
a2 == 5
b == 6


-Mike
 
R

Robert Bauck Hamar

I have two object types ClassA and ClassB

class ClassA {
public:
int data;
operator ClassB()
{
ClassB b;
b.data = data + 1;
return (b);
}
};

class ClassB {
public:
int data;
operator ClassA()
{
ClassB b;

I assume you meant ClassA b; ?
b.data = data - 1;
return(b);
}
}

There should be a ; here.
So... If I say:

ClassA a1, a2;
ClassB b;

a1.data = 5;
b = a1;
a2 = b;

then a2 should be identical to a1 and b should be 6.

First off I can't get this to compile because ClassB isn't know ClassA
at compile time...

class ClassB; //forward declaration of ClassB

class ClassA {
public:
int data;
operator ClassB(); //OK ClassB forward declared.
};

class ClassB {/*as declared above*/};

inline ClassA::eek:perator ClassB()
{
ClassA b;
b.data = data + 1;
return b;
}
Is it necesary to have int data in both classes or can A inherit from B
and vise versa?

If ClassB is derived from ClassA, then a ClassB object would contain a
ClassA subobject, and also it's data member. Or vice versa. Or both
classes could be derived from a common base class. What do you want to
do?
Can both the casting operators exist in only on of the classes?

Yes. It's called a constructor in the other class:

ClassB::ClassB(const ClassA &b) : data(b.data + 1) {}
 
J

JustSomeGuy

Robert said:
I assume you meant ClassA b; ?


There should be a ; here.


class ClassB; //forward declaration of ClassB

class ClassA {
public:
int data;
operator ClassB(); //OK ClassB forward declared.
};

class ClassB {/*as declared above*/};

inline ClassA::eek:perator ClassB()
{
ClassA b;
b.data = data + 1;
return b;
}


If ClassB is derived from ClassA, then a ClassB object would contain a
ClassA subobject, and also it's data member. Or vice versa. Or both
classes could be derived from a common base class. What do you want to
do?


Yes. It's called a constructor in the other class:

ClassB::ClassB(const ClassA &b) : data(b.data + 1) {}

Ok thats good... but why then not use constructors in both cases rather than
casting operators?
Thanks all!
 
P

Petec

JustSomeGuy said:
Robert Bauck Hamar wrote:


Ok thats good... but why then not use constructors in both cases
rather than casting operators?
Thanks all!

Robert is wrong; you can have a casting operator in both classes. See the
other replies.

- Pete
 
R

Robert Bauck Hamar

Robert is wrong; you can have a casting operator in both classes. See the
other replies.

I believe one of us is misunderstanding the OP. I have not stated that you
cannot have conversion functions[0] in both classes.

Assume:

class A {/*...*/} a;
class B {/*...*/};

There are now two ways to make the definition

B b = a;

legal:
* One can define the conversion function A::eek:perator B(), or
* one can define a constructor in B that can be called with a single
argument of type A. This constructor must not be marked explicit.

This is then called a user defined conversion. Why choose one
over the other? Maybe you can change class B but not class A, or maybe
the implementation of the classes makes one of the choices easier. Or
if you are defining a conversion between your class and some fundamental
type.

[0]: A 'conversion function' is defined by the standard to be a
memberfunction of a class, with the signature 'operator T()' where T is
a type.
 
J

JustSomeGuy

Robert Bauck Hamar said:
Robert is wrong; you can have a casting operator in both classes. See the
other replies.

I believe one of us is misunderstanding the OP. I have not stated that you
cannot have conversion functions[0] in both classes.

Assume:

class A {/*...*/} a;
class B {/*...*/};

There are now two ways to make the definition

B b = a;

legal:
* One can define the conversion function A::eek:perator B(), or
* one can define a constructor in B that can be called with a single
argument of type A. This constructor must not be marked explicit.

This is then called a user defined conversion. Why choose one
over the other? Maybe you can change class B but not class A, or maybe
the implementation of the classes makes one of the choices easier. Or
if you are defining a conversion between your class and some fundamental
type.

[0]: A 'conversion function' is defined by the standard to be a
memberfunction of a class, with the signature 'operator T()' where T is
a type.

Yes I've pretty much come to the same conclusion myself that I could have
implemented the copy constructor with the other class as a parameter...
However
I'm not sure that guarantees that if I call a function whose prototype is
myfunc(ClassA &a) with an instance of ClassB as the paramter, that the cast
operator to convert ClassB to ClassA will be invoked.
 
R

Robert Bauck Hamar

Yes I've pretty much come to the same conclusion myself that I could have
implemented the copy constructor with the other class as a parameter...
However
I'm not sure that guarantees that if I call a function whose prototype is
myfunc(ClassA &a) with an instance of ClassB as the paramter, that the cast
operator to convert ClassB to ClassA will be invoked.

No it should not. However if the prototype is myfunc(const ClassA &a),
then you would be able to call myfunc(b), which means
myfunc(ClassA::ClassA(b))
or
myfunc(b.operator ClassA()).
 
D

dumboo

hi there

#include <iostream>
#include <ostream>

class B;

class A
{
int data;

public:
A(int d = 0) : data (d) { }
operator B() const;
friend std::eek:stream& operator<<(std::eek:stream& os, const A& a)
{
return os << a.data;
}
};

class B
{
int data;

public:
B(int d = 0) : data (d) { }

operator A() const { return data - 1; }
friend std::eek:stream& operator<<(std::eek:stream& os, const B& b)
{
return os << b.data;
}
};

A::eek:perator B() const { return data + 1; }

int main()
{
A a1(5);
A a2;
B b;

b = a1;
a2 = b;

std::cout << "a1 == " << a1 << '\n'
<< "a2 == " << a2 << '\n'
<< "b == " << b << '\n';

return 0;
}

Output:

a1 == 5
a2 == 5
b == 6

i m bit confuse about all these examples, can u please explain it to me, or
point me to some good online resources :)

class A
{
....
operator B() const;
....
};

here are we overloading Constructor of B ???? as operator ?? in class "A" i
m really confuse...and really dont know what to say and how to phrase my
question....
 
M

Mike Wahler

dumboo said:
hi there



i m bit confuse about all these examples, can u please explain it to me, or
point me to some good online resources :)

There's only one online book I recommend:
Bruce Eckel's "Thinking in C++"
www.mindview.net

I strongly recommend getting some 'regular' books. See the
book reviews at www.accu.org
class A
{
...
operator B() const;
...
};

here are we overloading Constructor of B ????

No. A constructor always has the same name as
its class [1] e.g. a constructor for class A
would look like:

A(/* optional parameters */) /* constructor for class 'A' */
{
/* etc */
}
as operator ?? in class "A" i
m really confuse...and really dont know what to say and how to phrase my
question....

The function above ('operator B()') is known as a 'conversion
function' (sometimes called a 'conversion operator'. It converts
a type 'A' (the enclosing class type) to a type 'B' (indicated
by the 'B' in 'operator B()'. Conversion functions may not have
a return type or any parameters (the return type is indicated by
the function's name, and parameters would meet any need.)

The above allows code such as:

A a;
B b;

b = a; /* converts a type 'A' to a type 'B' */

Classes can also define conversion functions that convert
to built-in types, e.g.

operator int() { /* etc */ }

[1] Technically, constructors don't actually have names, but I find
it makes it easier to explain to a novice, since the syntax makes
it look like it has a name (the same as that of its class).

-Mike
 
M

Mike Wahler

Conversion functions may not have
a return type or any parameters (the return type is indicated by
the function's name, and parameters would
not

meet any need.)


oops!

-Mike
 

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,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top