Cass object returning a value by name?

L

Lilith

Sorry if the subject line is vague.

I *think* I've seen discussion in the past of this capability but I'm
unable to find it. Essentially I have a context in which at makes
sense to have a class object return an integer value when the object's
name is used.

class X {

int XNumber;


};
..
..
X a;
X b;
..
..
xxxCopy (a, b);

xxxCopy() is unrelated to class X and works on integer values that are
stored within its own system. My class has to store the number used
by the system that uses xxxCopy(). I know I could provide a member
function of X to return the value but using the name of the object and
not a method within it is more instinctive for my uses.

I think I've read that it's possible to over load an operator to
provide this functionality but at the time it was of interest but no
immediate need. Then again, I may have just had a dream about it.
 
J

Jerry Coffin

[ ... ]
Essentially I have a context in which at makes
sense to have a class object return an integer value when the object's
name is used.

class X {

int XNumber;

[ ... ]

operator int() { return XNumber; }

Keep in mind that this allows implicit conversion of an X to an int,
even when you may not want that. Conversion operators can be handy, but
they can also be somewhat dangerous.
 
L

Lilith

[ ... ]
Essentially I have a context in which at makes
sense to have a class object return an integer value when the object's
name is used.

class X {

int XNumber;

[ ... ]

operator int() { return XNumber; }

Keep in mind that this allows implicit conversion of an X to an int,
even when you may not want that. Conversion operators can be handy, but
they can also be somewhat dangerous.

Many thanks. I anticipated the hazard and have tried think of an
instance where this might be a problem but at this time I can't.
However, I'll be on the alert as I progress through this development
and if it presents a problem I'll go the less intuitive route.

Once more, thanks.
 
K

Kira Yamato

[ ... ]
Essentially I have a context in which at makes
sense to have a class object return an integer value when the object's
name is used.

class X {

int XNumber;

[ ... ]

operator int() { return XNumber; }

Keep in mind that this allows implicit conversion of an X to an int,
even when you may not want that. Conversion operators can be handy, but
they can also be somewhat dangerous.

Many thanks. I anticipated the hazard and have tried think of an
instance where this might be a problem but at this time I can't.
However, I'll be on the alert as I progress through this development
and if it presents a problem I'll go the less intuitive route.

A rule of thumb that I used to determine if conversion operator should
be used or not, is to ask myself if my class and the conversion type
obey the "is a" relationship in an object oriented fashion.

So, my question to you is this: is your class X an integer, in the OOP sense?
 
N

Niels Dekker - no return address

Jerry said:
operator int() { return XNumber; }

Basically Jerry is right, but you'd probably want to indicate that the
conversion does not modify your X object, by adding a "const":

class X {
int XNumber;
public:
operator int () const { return XNumber; }
};
Many thanks. I anticipated the hazard and have tried think of an
instance where this might be a problem but at this time I can't.
However, I'll be on the alert as I progress through this development
and if it presents a problem I'll go the less intuitive route.

The dangerous thing about those conversion operators is that their
conversion happens so "implicitly". Fortunately the next C++ Standard
will allow you to declare the conversion operator as "explicit". But I
guess your compiler won't support it yet. Anyway, if you want to know
more, read: "Explicit Conversion Operator Draft Working Paper (revision
3)", by Lois Goldthwaite, Michael Wong, Jens Maurer, and Alisdair
Meredith - www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf

[Oops, my original reply went to the wrong newsgroup: comp.lang.c It's
because of a bug in my good old (VERY old) newsgroup client. Hmmm,
maybe I should upgrade!]

Kind regards,
 
J

Jerry Coffin

[ .... ]
Basically Jerry is right, but you'd probably want to indicate that the
conversion does not modify your X object, by adding a "const":

Quite true. In fact, nearly _all_ conversion operators should be const
-- they should supply a value FROM the object, but the original object
should remain unchanged.
 
N

Niels Dekker - no return address

Jerry said:
In fact, nearly _all_ conversion operators should be const
-- they should supply a value FROM the object, but the original object
should remain unchanged.

What do you think of the (const) conversion operator of Boost's wrapper
template class value_initialized<T>? value_initialized<T> wraps an
object of type T, and it has a conversion operator to a reference-to-T,
providing full access to the object it wraps:

// From Boost: www.boost.org/libs/utility/value_init.htm
template<class T> class value_initialized {
public:
operator T&() const;
T& data() const;
...
};

I'm thinking of removing this conversion operator, and replacing it by a
set of dereference and arrow operators, overloaded for const and
non-const:

template<class T> class value_initialized {
public:
const T & operator*() const;
T & operator*();
const T * operator->() const;
T * operator->();
T& data() const;
...
};

Basically Fernando Cacciola - the creator and owner of
boost::value_initialized - already likes this idea, but I would
appreciate having your opinion as well :)


Kind regards,
 
J

Jerry Coffin

[ ... ]
Basically Fernando Cacciola - the creator and owner of
boost::value_initialized - already likes this idea, but I would
appreciate having your opinion as well :)

It looks pretty good to me, with the caution that (of course) it breaks
any existing code that uses the conversion. IMO, it's enough of an
improvement that I'd favor it unless the existing conversion was in
_really_ wide use.
 
L

Lilith

[ ... ]

Essentially I have a context in which at makes
sense to have a class object return an integer value when the object's
name is used.

class X {

int XNumber;

[ ... ]

operator int() { return XNumber; }

Keep in mind that this allows implicit conversion of an X to an int,
even when you may not want that. Conversion operators can be handy, but
they can also be somewhat dangerous.

Many thanks. I anticipated the hazard and have tried think of an
instance where this might be a problem but at this time I can't.
However, I'll be on the alert as I progress through this development
and if it presents a problem I'll go the less intuitive route.

A rule of thumb that I used to determine if conversion operator should
be used or not, is to ask myself if my class and the conversion type
obey the "is a" relationship in an object oriented fashion.

So, my question to you is this: is your class X an integer, in the OOP sense?

Within the context I'm dealing with I think I can say yes. To give a
little perspective...

The API I'm dealing with is Dark GDK, a game development API from The
Game Creators. It's free for personal use and give-away applications.
It says it'd designed for C++ but the only thing C++ about it that I
see is a bit of polymorphism. Otherwise the system is nothing more
than calls that seem more procedural than OO.

The basic "objects" of the system are sprites, images and bitmaps. One
doesn't declare a sprite, one determines a number to use to represent
a sprite (or image or bitmap) and passes it to a function. Apparently
the system maintains some sort of internal collection of these items
rather than the user keeping an object in their program. So,
procedurally I'd create an image by loading it from a file and assign
it a number, say 10, when I make the call to load the image. When I
want to assign a sprite to use the image I call

dbSprite (6, 128, 256, 10);

where 6 is the number I want to assign to the sprite. The 2nd and 3rd
parameters are the x and y position and 10 is the image number to use.
If I don't maintain the x and y position somewhere in my program I
have to make calls to other functions to retrieve them, once again by
sepcifying the intended sprite number, one at a time.

I'd rather encapsulate the entire thing in a class object so my
sprite, or whatever, knows what number it is, where it's supposed to
be and can act on its own information. I don't think the overhead for
the encapsulation is any worse than having to make two calls to know
what the x and y positions or it's rotation, offset or any other
attribute is.

The screen is always bitmap #0, so if I have a bitmap I'm drawing to
for my background, call it bitmap #1, and I'm ready to write it to the
screeen I make the call

dbCopyBitmap (1, 0, 0, 0, 0, 0);

where the 4th parameter is the number representing the screen and the
other zeros reperesent the upper left corner of source and
desitination to copy from/to. (There may be some other parameters
providing a rectangle to draw but I'm not going to look it up right
now.)

AAR, if I'm going to have to make a call like this I'd rather write

dbCopyBitmap (Background, 0, 0, Screen, 0, 0);

where Background would be an object of my bitmap class and, when
passed to the function would result in the numeric value of the bitmap
rather than calling

dbCopyBitmap (Background.getBitmapNumber(), 0, 0, Screen, 0, 0);

I know I could use enumeration but there are potential pitfalls there
too. Eventually, I'll probably encapsulate a CopyToScreeen ()
function within my bitmap class that has a call that makes to call to
the Dark GDK function and it won't matter so much. But I may want to
copy to other bitmaps by name also.
 
L

Lilith

Basically Jerry is right, but you'd probably want to indicate that the
conversion does not modify your X object, by adding a "const":

class X {
int XNumber;
public:
operator int () const { return XNumber; }
};

Got ya.
The dangerous thing about those conversion operators is that their
conversion happens so "implicitly". Fortunately the next C++ Standard
will allow you to declare the conversion operator as "explicit". But I
guess your compiler won't support it yet. Anyway, if you want to know
more, read: "Explicit Conversion Operator Draft Working Paper (revision
3)", by Lois Goldthwaite, Michael Wong, Jens Maurer, and Alisdair
Meredith - www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf

Thanks for the link. I'll have a look.
[Oops, my original reply went to the wrong newsgroup: comp.lang.c It's
because of a bug in my good old (VERY old) newsgroup client. Hmmm,
maybe I should upgrade!]
 
K

Kira Yamato

[ ... ]

Essentially I have a context in which at makes
sense to have a class object return an integer value when the object's
name is used.

class X {

int XNumber;

[ ... ]

operator int() { return XNumber; }

Keep in mind that this allows implicit conversion of an X to an int,
even when you may not want that. Conversion operators can be handy, but
they can also be somewhat dangerous.

Many thanks. I anticipated the hazard and have tried think of an
instance where this might be a problem but at this time I can't.
However, I'll be on the alert as I progress through this development
and if it presents a problem I'll go the less intuitive route.

A rule of thumb that I used to determine if conversion operator should
be used or not, is to ask myself if my class and the conversion type
obey the "is a" relationship in an object oriented fashion.

So, my question to you is this: is your class X an integer, in the OOP sense?

Within the context I'm dealing with I think I can say yes. To give a
little perspective...

The API I'm dealing with is Dark GDK, a game development API from The
Game Creators. It's free for personal use and give-away applications.
It says it'd designed for C++ but the only thing C++ about it that I
see is a bit of polymorphism. Otherwise the system is nothing more
than calls that seem more procedural than OO.

The basic "objects" of the system are sprites, images and bitmaps. One
doesn't declare a sprite, one determines a number to use to represent
a sprite (or image or bitmap) and passes it to a function. Apparently
the system maintains some sort of internal collection of these items
rather than the user keeping an object in their program. So,
procedurally I'd create an image by loading it from a file and assign
it a number, say 10, when I make the call to load the image. When I
want to assign a sprite to use the image I call

dbSprite (6, 128, 256, 10);

where 6 is the number I want to assign to the sprite. The 2nd and 3rd
parameters are the x and y position and 10 is the image number to use.
If I don't maintain the x and y position somewhere in my program I
have to make calls to other functions to retrieve them, once again by
sepcifying the intended sprite number, one at a time.

I'd rather encapsulate the entire thing in a class object so my
sprite, or whatever, knows what number it is, where it's supposed to
be and can act on its own information. I don't think the overhead for
the encapsulation is any worse than having to make two calls to know
what the x and y positions or it's rotation, offset or any other
attribute is.

The screen is always bitmap #0, so if I have a bitmap I'm drawing to
for my background, call it bitmap #1, and I'm ready to write it to the
screeen I make the call

dbCopyBitmap (1, 0, 0, 0, 0, 0);

where the 4th parameter is the number representing the screen and the
other zeros reperesent the upper left corner of source and
desitination to copy from/to. (There may be some other parameters
providing a rectangle to draw but I'm not going to look it up right
now.)

AAR, if I'm going to have to make a call like this I'd rather write

dbCopyBitmap (Background, 0, 0, Screen, 0, 0);

where Background would be an object of my bitmap class and, when
passed to the function would result in the numeric value of the bitmap
rather than calling

dbCopyBitmap (Background.getBitmapNumber(), 0, 0, Screen, 0, 0);

Actually, I prefer the second version over the first version. That is,
I prefer
dbCopyBitmap (Background.getBitmapNumber(), 0, 0, Screen, 0, 0);
over
dbCopyBitmap (Background, 0, 0, Screen, 0, 0);

The implicit conversion can hurt you later. For example, in the future
you might want to stream out the Background object. In that case, if
you keep the implicit integer conversion operator for Background, then
the following line

ofilestream << Background

might back-fire on you. It is fine if you absolutely sure that
Background class will never have other members other than the integer.
However, in that case, you probably should just use typedef anyway. On
the other hand, if you ever will have more members in Background, then
that implicit integer conversion will hide the oversight of the
programmer for not providing an << operator for Background class.

And this is just one example of implicit conversion trap.
 
N

Niels Dekker - no return address

Jerry said:
It looks pretty good to me, with the caution that (of course) it breaks
any existing code that uses the conversion. IMO, it's enough of an
improvement that I'd favor it unless the existing conversion was in
_really_ wide use.

Thanks! I'm glad that you agree that it would be better if a wrapper
class like boost::value_initialized wouldn't have a conversion operator,
returning a reference to the object it wraps...

Kind regards,

Niels
 

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,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top