-1

I have been attempting to create a function getLocation() that utilizes a pointer to return the value of the struct Location declared in the Character class. I was curious as to the problem with my syntax (or my structure). Knowing that the asterisk * should refer to the value, why is it that my function using an ampersand string& Character::getInventory is able to return the value of that particular index (its return does not need to be converted)?

Trying Location& Character::getLocation() {return position; } when run results in error C2679: binary '<<': no operator found

Nor Location* Which cannot be run as there is no conversion.

I read that the following is likely the most proper because it specifies the scope in which the structure resides, but still results in needing and returning a temporary.

Character::Location* const & Character::getLocation() {return &position; }

Any advice or input would be greatly appreciated, thanks in advance. Below is my main.cpp, which of course will show the hexadecimal address for Location.

#include <iostream>
#include <string>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::string;

class Character {

private:

    string name;
    string inventory[4];

public:

    struct Location {
        int x; int y;
    };
    Location position;

public:

    void Character::setName(string x) { name = x; }
    string Character::getName() { return name; }

    void Character::setLocation(int x, int y) {
        position.x = x; position.y = y;
    }

    Location* Character::getLocation() {return &position; }

    void Character::setInventory(string(&x)[4]) { for (int i = 0; i < 4; ++i) { inventory[i] = x[i]; } }
    string& Character::getInventory(int itemNumber) { return inventory[itemNumber]; }
};

void showUser(Character Character);

int main() {

        try {

            string items[4] = { "Sword", "Shield", "Potion", "Cloak" };

            Character CharacterI;

            CharacterI.setName("Some Character");
            CharacterI.setInventory(items);
            CharacterI.setLocation(1, 30);

            cout << "\n" << "Retrieving Character Info..." << "\n" << endl;
            showUser(CharacterI);

        }
        catch (std::exception & e) {
            cerr << "\nError : " << e.what() << '\n';
        }

    system("pause");
    return 0;
}

void showUser(Character character) {
    cout << "Name : " << character.getName() << endl;
    cout << "Location : " << character.getLocation() << endl;
    for (int i = 0; i < 4; ++i) {
        cout << "Inventory " << i + 1 << " : " << character.getInventory(i) << endl;
    }
}
Austin
  • 195
  • 1
  • 4
  • 13
  • 1
    Moving this to a comment instead of an answer since it doesn't really answer your question: Your functions `getLocation` and `setLocation` create temporary instances of `struct Location`, each of which is destroyed when the function returns. You need to create a member variable to hold the Character's location, then set/get from that variable instead. – Carlton Sep 15 '15 at 17:01
  • You claim to want to do something very simple, then you post a wall of code. Please post a small, self-contained code sample that illustrates the problem you're trying to fix. – juanchopanza Sep 15 '15 at 17:03
  • @Carlton Want to make that an answer? It's correct. Actually I see it was an answer and you deleted it. Why? – Patrick87 Sep 15 '15 at 17:04
  • I re-read the OP after I wrote it and decided that while my answer may be correct, it didn't seem to actually answer the question, which seemed to be about how the return value of the functions is converted. I'll re-post as an answer if you think that's appropriate. – Carlton Sep 15 '15 at 17:08
  • 1
    I second @juanchopanza. Try a trivial class which holds an int.-- Specifically understand that while yes, `*` signifies "value" (i.e. a dereferencing of an address) in an *expression*, it signifies the opposite in a *declaration*. This is because C's/C++'s declaration syntax mimics expressions and shows *what you would need to do to the identifier* being declared in order to obtain the base type, here `Location`. If you need to dereference the identifier, then the identifier denotes a pointer (-like thing). – Peter - Reinstate Monica Sep 15 '15 at 17:11
  • Thanks to all for your responses. @Carlton, that was a valuable point. I've since made changes, but the problem of returning the value still persists. – Austin Sep 15 '15 at 17:35
  • @juanchopanza the code outside the class is/was unnecessary, I'm admittedly a bit of a novice. I included it in the hope that it would be of benefit. – Austin Sep 15 '15 at 17:41
  • @Austin I updated my answer with an example. Not sure what problem you're having but hopefully the example helps. – Carlton Sep 15 '15 at 17:43

1 Answers1

1

Ok, I think I understand the question better now. The reason why getInventory can successfully return a reference while getLocation does not is because getLocation returns a reference to a temporary variable, which is not good. See the link in @NathanOliver's comment for details. Additionally, to paraphrase a previous comment by @Peter Schneider, an * in an expression dereferences a pointer to return a value, while in a declaration it signifies that a variable will be of pointer type. The two usages are more or less opposites of each other. Example:

int* p = new int;  //Declares a pointer to int
int x = *p;        //Dereferences a pointer and returns an int

What you need to do is create a member variable to hold the Character's location, then set/get from that variable instead of creating temporaries. You did this already for name and inventory, just keep using that same pattern.

Additionally, whenever you use the Location struct outside of the Character class scope, you need to fully-qualify it with Character::Location.

Example:

#include <iostream>
using namespace std;

class Character {
public:
    struct Location {
        int x;
        int y;
    };

    Location loc;

    void SetLocation(int x, int y) {loc.x = x; loc.y = y;}
    Location& GetLocation() {return loc;}
};


int main ()
{
    Character c;
    c.SetLocation(1,42);
    Character::Location l = c.GetLocation();

    cout << l.x << endl << l.y << endl;

    return 0;
}

Output:

1

42

Carlton
  • 4,217
  • 2
  • 24
  • 40
  • Hey, thanks; my question was a little but confusing. This alleviated the majority of my problems. I want to give you credit, but for the sake of posterity I think @Peter Schneider 's comment above " * signifies "value" (i.e. a dereferencing of an address) in an expression, it signifies the opposite in a declaration" is the other half of the problem. If you include that I would be happy to accept it. – Austin Sep 15 '15 at 18:40
  • 1
    @Austin: I updated my answer. – Carlton Sep 15 '15 at 18:51