为什么不能通过 using 指令 vs 封闭在命名空间中来识别友元函数?
Why can't friend function be recognized with using directive vs enclosing in namespace?
为什么朋友operator<<
在cpp文件和using指令中定义时无法识别?
我在头文件中,game.h
namespace uiuc {
class Game {
public:
Game();
void solve();
friend std::ostream & operator<<(std::ostream & os, Game & game);
private:
std::vector<Stack> stacks;
};
在我的 cpp 文件中,game.cpp
:
#include "game.h"
using namespace uiuc;
std::ostream & operator<<(std::ostream & os, Game & game) {
for (unsigned long i = 0; i < game.stacks.size(); ++i) {
os << "Stack [" << i << "]: " << game.stacks[i] << std::endl;
}
return os;
}
我得到的错误是:
g++ -std=c++1z -g -Wfatal-errors -Wall -Wextra -pedantic -MMD -MP -c game.cpp
game.cpp:5:38: fatal error: 'stacks' is a private member of 'uiuc::Game'
for (unsigned long i = 0; i < game.stacks.size(); ++i) {
^
./game.h:17:22: note: declared private here
std::vector<Stack> stacks;
^
1 error generated.
make: *** [Makefile:18: game.o] Error 1
这在头文件中定义友元函数时有效。我决定移动它,因为对于相同的方法,我收到一个重复符号的链接器错误,所以我决定看看如果我将函数定义移动到 cpp 文件会发生什么。我错过了什么?然而,当我将定义包含在 namespace uiuc
中时,它消除了这个错误,我又回到了链接器错误。链接器错误 NOT 这个问题是关于什么的。
为什么编译器不能意识到这是一个友元函数并且可以访问私有变量?
首先在 class 中声明为 friend
的函数放置在封闭的命名空间中,因此您要定义的函数必须在 uiuc
命名空间中定义。
您可能假设如果您使用 using namespace uiuc;
,新的 declarations/definitions 将被放入 uiuc
命名空间,但事实并非如此。 using namespace
只影响名称的查找,而不影响放置 declarations/definitions 的位置。
因此,您现在定义的函数是 global 命名空间范围内的 operator<<(std::ostream & os, uiuc::Game & game)
(它不是 friend
的 uiuc::Game
),而不是 uiuc
命名空间中的 operator<<(std::ostream & os, Game & game)
。
所以你需要正确打开命名空间:
#include "game.h"
namespace uiuc {
std::ostream & operator<<(std::ostream & os, Game & game) {
for (unsigned long i = 0; i < game.stacks.size(); ++i) {
os << "Stack [" << i << "]: " << game.stacks[i] << std::endl;
}
return os;
}
}
此外,关于链接器错误:如果您在 class 定义之外 定义了 friend
函数,并且没有将其指定为 inline
,那么它将是一个non-inline函数,意味着它可能只有一个定义在只有一个 翻译单元。这通常会阻止将定义放在 header 中,因为 header 通常包含在多个翻译单元中。
如果您在 class body 中 内部定义函数 body 或使用 inline
关键字声明它,那么它将是一个 内联函数,意思是必须在每个使用它的翻译单元中定义它,这通常意味着定义必须放在header文件中。
为什么朋友operator<<
在cpp文件和using指令中定义时无法识别?
我在头文件中,game.h
namespace uiuc {
class Game {
public:
Game();
void solve();
friend std::ostream & operator<<(std::ostream & os, Game & game);
private:
std::vector<Stack> stacks;
};
在我的 cpp 文件中,game.cpp
:
#include "game.h"
using namespace uiuc;
std::ostream & operator<<(std::ostream & os, Game & game) {
for (unsigned long i = 0; i < game.stacks.size(); ++i) {
os << "Stack [" << i << "]: " << game.stacks[i] << std::endl;
}
return os;
}
我得到的错误是:
g++ -std=c++1z -g -Wfatal-errors -Wall -Wextra -pedantic -MMD -MP -c game.cpp
game.cpp:5:38: fatal error: 'stacks' is a private member of 'uiuc::Game'
for (unsigned long i = 0; i < game.stacks.size(); ++i) {
^
./game.h:17:22: note: declared private here
std::vector<Stack> stacks;
^
1 error generated.
make: *** [Makefile:18: game.o] Error 1
这在头文件中定义友元函数时有效。我决定移动它,因为对于相同的方法,我收到一个重复符号的链接器错误,所以我决定看看如果我将函数定义移动到 cpp 文件会发生什么。我错过了什么?然而,当我将定义包含在 namespace uiuc
中时,它消除了这个错误,我又回到了链接器错误。链接器错误 NOT 这个问题是关于什么的。
为什么编译器不能意识到这是一个友元函数并且可以访问私有变量?
首先在 class 中声明为 friend
的函数放置在封闭的命名空间中,因此您要定义的函数必须在 uiuc
命名空间中定义。
您可能假设如果您使用 using namespace uiuc;
,新的 declarations/definitions 将被放入 uiuc
命名空间,但事实并非如此。 using namespace
只影响名称的查找,而不影响放置 declarations/definitions 的位置。
因此,您现在定义的函数是 global 命名空间范围内的 operator<<(std::ostream & os, uiuc::Game & game)
(它不是 friend
的 uiuc::Game
),而不是 uiuc
命名空间中的 operator<<(std::ostream & os, Game & game)
。
所以你需要正确打开命名空间:
#include "game.h"
namespace uiuc {
std::ostream & operator<<(std::ostream & os, Game & game) {
for (unsigned long i = 0; i < game.stacks.size(); ++i) {
os << "Stack [" << i << "]: " << game.stacks[i] << std::endl;
}
return os;
}
}
此外,关于链接器错误:如果您在 class 定义之外 定义了 friend
函数,并且没有将其指定为 inline
,那么它将是一个non-inline函数,意味着它可能只有一个定义在只有一个 翻译单元。这通常会阻止将定义放在 header 中,因为 header 通常包含在多个翻译单元中。
如果您在 class body 中 内部定义函数 body 或使用 inline
关键字声明它,那么它将是一个 内联函数,意思是必须在每个使用它的翻译单元中定义它,这通常意味着定义必须放在header文件中。