Using friendship with save file function

I ran into a little problem when coding some stuff. I am wondering if the following situation is a good place to use C++ friendship, this would be my first time I've needed to use it. Another lengthy post, thanks in advance if you read this. =)

First off:
As I understand it, "const" should be used at the end of a function declaration to mean that it cannot modify its member values. So naturally I put const at the end of my save function, since it only uses the member data to save a file, but doesn't modify it.

Basically, I have a World class with a save() function, and this save function saves some header data + the data for each Tile object in the World.

The issue is that World::save() needs to call each Tile's save(), but I do not want the user to be able to do something like world.getTiles()[0].save(f) in their own (main or whatever) function.


This is how I have my trimmed program set up after adding const
1
2
3
4
5
6
7
8
9
10
class Tile {
  public:
    Tile();
    void save() const; //notice it's public, to be called from World::save()
};
Tile::Tile() {}
void Tile::save() const
{
    std::cout << "Tile saved to file!\n";
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class World {
  public:
    World();
    void save() const;
    const std::vector<Tile>& getTiles() const;
  private:
    std::vector<Tile> mTiles;
};

World::World()
: mTiles(10) {}
void World::save() const
{
    //save "header" stuff (not shown)
    
    //save each tile:
    for (int i = 0; i < mTiles.size(); i++)
        mTiles[i].save();
}
const std::vector<Tile>& World::getTiles() const
{
    return mTiles;
}

1
2
3
4
5
6
7
8
int main()
{
    World world;
    world.save();
    world.getTiles()[0].save(); //This is technically legal,
                     //but I don't want it to be.
    return 0;
}


Here is the modified Tile class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Tile {
  friend class World;
  public:
    Tile();

  private:
    void save() const; //private, but World can still call it
};
Tile::Tile() {}
void Tile::save() const
{
    std::cout << "Tile saved to file!\n";
}

...
world.getTiles()[0].save() //is now compile-time error (which is good) 


Again, to reiterate, I'm just wondering if this a good use case for friendship or is my design flawed?

PS: Another method that "works" is to keep World::save() const, but make Tile::save() non-const, so that the compiler still gives an error, but this is just screaming bad practice to me, so friendship seems like the best choice here?
Thanks for reading, I just want to make sure I'm understanding this correctly :)
Last edited on
Topic archived. No new replies allowed.