tags:

views:

220

answers:

8

In c++ can we cast an object to an integer ?

Clarifying my question - Suppose i have created an interface that do all the file management thing like file create, open, read, write and i want to have a unique handle of every instance of a file so for this can i create a file handle from every instance of the file interface by just type casting that instance to integer ?

To all - I hope now i am clear.

+5  A: 

Not all objects. Every object in C++ has a type. That type of an object defines whether a cast to int exists, and if so, what algorithm is used.

MSalters
+3  A: 

If you have an object and want to cast it to int then you need to explicitly provide operator int for that class.

Naveen
A: 

Edit: Since you are mapping files to a unique handle, you can use a std::vector<std::string> or a vector<shared_ptr<fstream> > or a vector<FILE*>.

On a POSIX-compliant system there is also fileno to convert a FILE* into its file descriptor which is an int.


To get the hash: Use the hash_value function from boost.

To convert any value to integer lexically: Use the lexical_cast<int> function from boost

To cast the value to integer: Just use (int)value.

For the above to work, the class you're going to convert needs to implement some special member functions e.g. operator<< and operator int.

To convert an object into an arbitrary unique integer, use (int)&value.

To get a random integer, use rand().

KennyTM
A: 

I would rather convert to a long type. This is safer when a pointer value is converted to an integral type on an x64 machine. You can just use reinterpret_cast<long>(myInterfacePointer) in that case.

Kerido
Not `long`. `uintptr_t`.
asveikau
Also, casting pointers to int is a bad idea which is treading water.
Potatoswatter
You assume LP64, which is dangerous since Windows on both x64 and IA64 uses LLP64, and a `long` is 32 bit. asveikau is right, you should use uintptr_t, or if it's not available fake it up in a portability header.
Steve Jessop
A: 

you can, but it depend on the sizeof(YourObject) compared to sizeof(int), by casting any object to int you will access the first 4 bytes part of your object (assuming sizeof(int) == 4), if your object is smaller than sizeof(int) somewhere you will get access violation or crash. to cast :

`

 MyObject object;
 int castedObject = *((int*)&object);

`

to cast without pointer intermediate, you must provide typecast operator inside MyObject class. or you can declare global static function of int& operator=(const MyObject& object){...}

uray
That makes little sense and is unlikely to work, much less to guarantee any particular behavior at all.
Potatoswatter
well, before the question was edited, its unclear what he wanted, i just describe how to force cast any object to int regardless its effects
uray
Potatoswatter
uray's point is valid, i.e. you can directly cast the first sizeof(int) bytes of an object's in-memory representation to an int. It's unlikely that this is ever what you want, still it does answer the OP's question. Whether or not sizeof(int) is 4 is immaterial to the answer.
Roel
@Roel: it's not immaterial because it determines the behavior of the program!
Potatoswatter
The program will behave differently depending on sizeof(int), but there was nothing in the question about what the behavior should be. My remark was in relation to your '1. sizeof(int) == 4 is a poor assumption' - what assumption is made about the size of int doesn't matter, it can be 4 or 8 or whatever, and still the fundamental answer is the same, namely that you can cast the first x bytes to an object to an integer, period. Whether or not that cast makes any sense is a whole different matter. All your points go into whether or not it *should* be done, which is irrelevant to the question.
Roel
+1  A: 
class File
{
 public:
  ...
  ...
  operator int() { return int(this); }
  ...
}

Then

File myFile;
int myFileHandle = myFile;
ardsrk
`int` is not guaranteed to be as big as a pointer. Most 64-bit systems have 64-bit pointers and 32-bit ints so two different pointers can alias to the same int. You're better off using pointers as ID's and avoiding int entirely.
Potatoswatter
@Potatoswatter - Yes, you are right. Can u elaborate on how to use the pointer as Id's?
khushi
@khushi: what do you need an id to do? `void*` supports casting back to the original pointer type and testing for equality.
Potatoswatter
A: 

Why not just get the file descriptor/handle/whatever ID from the operating system and use that? Most systems have some kind of concept like that.

Consider using void * instead of int for the handles if you really want them to be pointers. Then casting a pointer-to-object to a handle is easy, and you can still hide the implementation away.

Potatoswatter
yes, u r right but i have limitation on this part that i have to generate this file handle.
khushi
generate UUID for each instance maybe?
uray
@khushi: what limitations do you have on the file handle? What do you need that an `int` can do but a `void*` can't?
Potatoswatter
A: 

In response to @potatoswatter's comment to my first response.

I don't like the idea of casting objects. I would rather use a hashing function that produces an integer hash, say based on the filename or read/write flags. Now, I have to post another answer

class File
{
 public:
  ...
  ...
  operator int();
  ...
 private:
  char fileName[];
  int flags;
};

The integer conversion operator is now a hashing function:

File::operator int()
{
 int hash = 0;
 int c;
 char *str = fileName;

 while (c = *str++)
    hash += c;

 hash += flags;

 return hash;
}

I know the hash function is lousy. But you can avoid casts that are lousier and come up with your own hashing function that suits your needs better.

ardsrk
In this case, IMO you'd be much better off using a named function (`getHash()`). Casting classes to primitives probably only makes sense when the class emulates a primitive to begin with.
visitor