Sign in to follow this  
Plasmarobo

Passing Object Pointers/ pointer initilization

Recommended Posts

Okay, let's say I have a vector of objects and NEED to return an object pointer to one of those. How do I do that? This is What I have now:
tItem* ItemsData::GetItem(int id)
{
for(int j=0; j=ItemDataBase.size(); j++)
{
        if(ItemDataBase[j].id == id)
        {
        tItem* ItemPtr = ItemDataBase[j];
        return ItemPtr;
        }
}
tItem* ItemPtr = ItemDataBase[0];
return ItemPtr;
}


Okay, I get a In member function `tItem* ItemsData::GetItem(int)': error: cannot convert `tItem' to `tItem*' in initialization error: cannot convert `tItem' to `tItem*' in initialization Which is annoying, because I need to return a pointer. Nothing else. Basically this return a pointer that I pass to another function.

Share this post


Link to post
Share on other sites
Since you said a vector of objects I'm gonna assume it's not a vector of pointers to objects. In which case I think you need to do:

tItem* ItemPtr = &ItemDataBase[j];

Goodluck.

Share this post


Link to post
Share on other sites
Ha ha ha, no.... it is a vector of the actual objects. It is where I store them all. Basically I load them from a file into this vector. I have another structure that needs to link to the items. Copying objects uses to much memory, so I figured that linking to the vector objects with pointer is the best, most effiecent way to "reference" them. I don't want to get into "Singletons" since I have no Idea what they are....

Share this post


Link to post
Share on other sites
I'm not sure what singletons are either :O Sorry if I couldn't help, I thought that is what you needed but I can't tell if you were saying it didn't work or saying you didn't mean a vector of pointers to objects...Either way, I hope you figure it out.

Goodluck

Share this post


Link to post
Share on other sites
The concept of a Singleton is totally irrelevant here - put it out of your mind.

You get the error that you can't convert because, well, a pointer to something isn't the same as the thing, and you can't pretend it is (implicitly convert). The use of the '&' sign in the indicated manner takes the address of the object, i.e. yields a pointer to it.

However, this being C++, you should strongly consider returning by reference instead. This allows you to work with pointer behaviour (i.e. you alias the object rather than copying it, and so calling mutating functions on the return value causes changes to be "seen" in the vector) but object syntax (i.e. the calling code is written as if it had an object, and you don't need that ugly address-of when you write the function). It's also more specific; you can do less with a reference than you could with a pointer, but that's exactly why you *should* use the reference when you don't need the pointer-only functionality: it protects you from mistakes and communicates more to maintenance programmers.

By the way, you need not and should not create temporary variables just for a value that's returned immediately; you can return any kind of expression. Returning item 0 by default when something isn't found is also a bad idea: the calling code doesn't know whether the item was not found, or found in position 0. This is one good reason to use a pointer instead: you can validly return a null pointer, but creating a null reference puts you in undefined-behaviour land. Oh, and while I'm at it, this searching loop is one you needn't write yourself; the standard library provides :)

So, you have options:


#include <algorithm> // and all the other stuff you have
using namespace std;

struct matchingId {
int id;
matchingId(int id): id(id) {}
bool operator() (const tItem& item) { return item.id == id; }
};

typedef vector<tItem>::iterator iter;

// Return a pointer, which is null if not found.
tItem* ItemsData::GetItem(int id) {
iter result = find_if(ItemDataBase.begin(),
ItemDataBase.end(),
matchingId(id));
// dereferencing an iterator gives you an object. Then we can get a pointer
// to it.
if (result == ItemDataBase.end()) { return 0; }
else { return &(*result); }
}

// Return a reference; throw an exception if not found.
tItem& ItemsData::GetItem(int id) {
iter result = find_if(ItemDataBase.begin(),
ItemDataBase.end(),
matchingId(id));
// dereferencing an iterator gives you an object,
// which we return by reference.
if (result == ItemDataBase.end()) { throw std::exception("not found"); }
else { return *result; }
}

// Return the iterator directly. The calling code has to be able to get at
// the 'end' iterator in order to check if the item was found.
// This approach is more suitable for private helper functions, normally.
iter ItemsData::GetItem(int id) {
return find_if(ItemDataBase.begin(),
ItemDataBase.end(),
matchingId(id));
}

// Return an index into the vector of the found item, or -1 if not found.
// Vectors provide "random access" iterators that are basically already
// pointers; we can thus do addition and subtraction ("pointer arithmetic")
// with them. However, to be more general, I have used the function
// std::distance. It is specially designed so that it will optimize into that
// subtraction when possible, but still yield a valid result (in more time) for
// containers providing other sorts of iterators.
int ItemsData::GetItem(int id) {
iter position = find_if(ItemDataBase.begin(),
ItemDataBase.end(),
matchingId(id));
int dist = std::distance(ItemDataBase.begin(), position);
if (dist == ItemDataBase.size()) { return -1; }
else { return dist; }
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this