Okay, I have looked all over for an answer to this.
I am trying to set up a system where an object's private members can be modified only through two member functions of a separate class.
Here is the header content of the object to be modified, table.h:
#ifndef TABLE_H
#define TABLE_H
#include "party.h"
/*
Seats a party for their dining experience at the restaurant.
*/
class table
{
friend void server::seatGuests(const table &, const party &);
friend void server::cleanTable(const table &);
private:
const unsigned int cap_; //guest capacity (shouldn't change)
const unsigned int id_; //table id (shouldn't change)
mutable bool isTaken_; //flag (changeable by friend functions)
party *const group_; //party seated at the table (starts off as null)
public:
table::table(const unsigned int id, const unsigned int cap = 4); //ctor
inline const unsigned int table::getCap() const { return cap_; }
inline const unsigned int table::getId() const { return id_; }
inline const bool table::isTaken() const { return isTaken_; }
inline const party *const table::getParty() const { return group_; };
};
void server::seatGuests(const table &t, const party &p)
{
t.isTaken_ = false;
}
#endif // TABLE_H
here is server.h:
class server : public employee
{
private:
public:
explicit server::server();
void server::seatGuests(const table &, const party &);
void server::cleanTable(const table &);
};
...
I am getting the following error:
member "table::isTaken_" (declared at line 17) is inaccessible
The server.h file is included in table.h indirectly, as party.h includes restaurant.h which includes server.h.
I tried putting this in table.h before:
class server;
namespace server {
void server::seatGuests(const table &, const party &);
void server::cleanTable(const table &);
}
But this just gave me more headaches, as the compiler would spit out something like, "class server has no member 'seatGuests' or 'cleanTable'", which I figured was due to some inclusion conflict. This conflict is why I've declared the function in the original server.h file and not in the table.h file.
That being said, sources I've read such as this one state that the implementation of the friend function should be in the class whose data is being modified, which is what I've done.
All that aside, the compiler still thinks the member data is not accessible. Can anyone see what I'm doing wrong here?
Let me know if you want me to post more code.
Thanks in advance.
EDIT
Apologies for the delay in posting the compiler output. Please see below:
> Executing task: clang++ -Wall -std=c++17 -stdlib=libc++ -o main.out /Users/ajm/Projects/restaurant/cpp/main/main.cpp -I/Users/ajm/Projects/restaurant/cpp/main/ -I/Users/ajm/Projects/restaurant/cpp/restaurant/ -I/Users/ajm/Projects/restaurant/cpp/people/ -I/Users/ajm/Projects/restaurant/cpp/people/workers/ -I/Users/ajm/Projects/restaurant/cpp/data/ --debug <
In file included from /Users/ajm/Projects/restaurant/cpp/main/main.cpp:1:
In file included from /Users/ajm/Projects/restaurant/cpp/main/simulation.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/restaurant/restaurant.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/restaurant/tablespace.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/restaurant/table.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/people/workers/server.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/people/workers/employee.h:5:
In file included from /Users/ajm/Projects/restaurant/cpp/main/../data/job.h:4:
/Users/ajm/Projects/restaurant/cpp/people/party.h:25:16: error: unknown type name 'restaurant'
void start(restaurant &spot);
^
In file included from /Users/ajm/Projects/restaurant/cpp/main/main.cpp:1:
In file included from /Users/ajm/Projects/restaurant/cpp/main/simulation.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/restaurant/restaurant.h:4:
In file included from /Users/ajm/Projects/restaurant/cpp/restaurant/tablespace.h:4:
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:8:11: error: redefinition of 'server' as different kind of
symbol
namespace server
^
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:7:7: note: previous definition is here
class server;
^
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:10:23: error: unknown type name 'table'
void seatGuests(const table &t, const party *const p);
^
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:11:23: error: unknown type name 'table'
void cleanTable(const table &t);
^
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:13:31: error: unknown type name 'table'
void server::seatGuests(const table &t, const party *const p)
^
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:18:31: error: unknown type name 'table'
void server::cleanTable(const table &t)
^
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:42:25: error: out-of-line declaration of 'seatGuests' does not
match any declaration in 'server'
friend void server::seatGuests(const table &t, const party *const p);
^~~~~~~~~~
/Users/ajm/Projects/restaurant/cpp/restaurant/table.h:43:25: error: out-of-line declaration of 'cleanTable' does not
match any declaration in 'server'
friend void server::cleanTable(const table &t);
^~~~~~~~~~
8 errors generated.
The terminal process terminated with exit code: 1
The declaration of server::seatGuests
and server::cleanTable
must appear before the friend
declaration in table
. #include "server.h"
appears before the declaration of table
so that should be enough right? Well, server
includes table
and table
includes server
so we have cyclic dependencies. To get around this, table
should include server
and server
should forward declare table
.
// table.h
#include "party.h"
class table
{
friend void server::seatGuests(const table &, const party &);
friend void server::cleanTable(const table &);
};
// server.h
class table;
class party;
class server : public employee
{
public:
explicit server();
void seatGuests(const table &, const party &);
void cleanTable(const table &);
};
Cyclic dependencies and friend declarations seem like bad design to me. Instead of using a forward declaration to get around this, you might want to rethink the design. Find a way to avoid the cycle and avoid the friend declarations. My answer is a workaround, not a solution.