C++:成员不可访问 - 使用友元函数允许一个 class 修改另一个 class 成员数据
C++: Member is inaccessible - using friend function to allow one class to modify another class member data
好的,我找遍了这个问题的答案。
我正在尝试建立一个系统,其中对象的私有成员只能通过单独 class 的两个成员函数进行修改。
这里是要修改的对象的头部内容,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
这里是 server.h:
class server : public employee
{
private:
public:
explicit server::server();
void server::seatGuests(const table &, const party &);
void server::cleanTable(const table &);
};
...
我收到以下错误:
member "table::isTaken_" (declared at line 17) is inaccessible
server.h 文件间接包含在 table.h 中,因为 party.h 包含 restaurant.h,后者包含 server.h.
我试过把这个放在 table.h 之前:
class server;
namespace server {
void server::seatGuests(const table &, const party &);
void server::cleanTable(const table &);
}
但这让我更加头疼,因为编译器会吐出类似 "class server has no member 'seatGuests' or 'cleanTable'" 的内容,我认为这是由于包含冲突造成的。这种冲突是我在原始 server.h 文件而不是 table.h 文件中声明该函数的原因。
话虽这么说,我读过的来源如 this one 指出 friend 函数的实现应该在数据被修改的 class 中,这就是我所知道的完成。
除此之外,编译器仍然认为成员数据不可访问。谁能看出我在这里做错了什么?
如果你想让我post更多代码,请告诉我。
提前致谢。
编辑
对于 post 编译器输出的延迟表示歉意。请看下面:
> 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
server::seatGuests
和server::cleanTable
的声明必须出现在table
中的friend
声明之前。 #include "server.h"
出现在 table
的声明之前,这样就足够了吧?好吧,server
包含 table
而 table
包含 server
所以我们有循环依赖。为了解决这个问题,table
应该包含 server
并且 server
应该转发声明 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 &);
};
循环依赖和友元声明对我来说似乎是糟糕的设计。您可能需要重新考虑设计,而不是使用前向声明来解决这个问题。找到一种方法来避免循环并避免朋友声明。 我的回答是解决方法,而不是解决方案。
好的,我找遍了这个问题的答案。
我正在尝试建立一个系统,其中对象的私有成员只能通过单独 class 的两个成员函数进行修改。
这里是要修改的对象的头部内容,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
这里是 server.h:
class server : public employee
{
private:
public:
explicit server::server();
void server::seatGuests(const table &, const party &);
void server::cleanTable(const table &);
};
...
我收到以下错误:
member "table::isTaken_" (declared at line 17) is inaccessible
server.h 文件间接包含在 table.h 中,因为 party.h 包含 restaurant.h,后者包含 server.h.
我试过把这个放在 table.h 之前:
class server;
namespace server {
void server::seatGuests(const table &, const party &);
void server::cleanTable(const table &);
}
但这让我更加头疼,因为编译器会吐出类似 "class server has no member 'seatGuests' or 'cleanTable'" 的内容,我认为这是由于包含冲突造成的。这种冲突是我在原始 server.h 文件而不是 table.h 文件中声明该函数的原因。
话虽这么说,我读过的来源如 this one 指出 friend 函数的实现应该在数据被修改的 class 中,这就是我所知道的完成。
除此之外,编译器仍然认为成员数据不可访问。谁能看出我在这里做错了什么?
如果你想让我post更多代码,请告诉我。
提前致谢。
编辑
对于 post 编译器输出的延迟表示歉意。请看下面:
> 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
server::seatGuests
和server::cleanTable
的声明必须出现在table
中的friend
声明之前。 #include "server.h"
出现在 table
的声明之前,这样就足够了吧?好吧,server
包含 table
而 table
包含 server
所以我们有循环依赖。为了解决这个问题,table
应该包含 server
并且 server
应该转发声明 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 &);
};
循环依赖和友元声明对我来说似乎是糟糕的设计。您可能需要重新考虑设计,而不是使用前向声明来解决这个问题。找到一种方法来避免循环并避免朋友声明。 我的回答是解决方法,而不是解决方案。