我正在尝试构建一个program,我从互联网上下载了它的源代码。当我尝试编译它时,出现错误信息
friend declaration specifying a default argument must be the only declaration
这是有问题的代码:
typedef int Var;
struct Lit {
int x;
// Use this as a constructor:
friend Lit mkLit(Var var, bool sign = false);
bool operator == (Lit p) const { return x == p.x; }
bool operator != (Lit p) const { return x != p.x; }
bool operator < (Lit p) const { return x < p.x; }
inline Lit mkLit(Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; }
我发现了几个可以解决此问题的问题,但问题相当深刻,我不太理解这些解释。 answer to this question表示我可以通过以下操作来解决问题:将
mkLit
的内联定义移到结构之前,从好友函数声明中删除默认参数,然后将其移至内联定义。它是否正确?但更简单地说,我不明白为什么结构需要 friend 功能,因为它的成员无论如何都是公共(public)的。接受的this question答案给出了一个基于参数的查找的答案(我的无知使我无法理解),但是我看不到它在这种情况下适用。
仅删除好友函数声明并将默认参数移至内联函数定义是否有任何缺点?如果是这样,您能举一个简单的例子吗?
最佳答案
我花了一段时间才知道,但最终我发现了。
因此,我忽略了误导性的标题(已经足够answered byuser463035818 IMHO了),并专注于
引起了我的注意。
因此,我不再重复关于friend
和访问公共(public)成员的说法,因为我认为此错误涉及另一个问题。
首先,我在coliru上尝试了OP的示例(有一点点修复和一个main()
进行测试):
#include <iostream>
typedef int Var;
struct Lit {
int x;
// Use this as a constructor:
friend Lit mkLit(Var var, bool sign = false);
bool operator == (Lit p) const { return x == p.x; }
bool operator != (Lit p) const { return x != p.x; }
bool operator < (Lit p) const { return x < p.x; }
};
inline Lit mkLit(Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; }
int main()
{
Lit lit2 = mkLit(123, false);
std::cout << "lit2.x: " << lit2.x << '\n';
return 0;
}
输出:
g++ (GCC) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
lit2.x: 246
Live Demo on coliru
嗯是的运行良好。
然后我这次用
clang HEAD 8.0.0
在wandbox上做了同样的事情:Start
prog.cc:7:16: error: friend declaration specifying a default argument must be a definition
friend Lit mkLit(Var var, bool sign = false);
^
prog.cc:12:14: error: friend declaration specifying a default argument must be the only declaration
inline Lit mkLit(Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; }
^
prog.cc:7:16: note: previous declaration is here
friend Lit mkLit(Var var, bool sign = false);
^
2 errors generated.
1
Finish
Live Demo on wandbox
我们到了。
因此,我试图了解
clang
抱怨什么。最后,我发现
clang
可以找到Lit Lit::mkLit()
,但与以后定义的Lit mkLit()
不匹配。这可以通过在
mkLit()
之前插入的struct Lit
原型(prototype)来解决:typedef int Var;
Lit mkLit(Var var, bool sign = false);
struct Lit {
int x;
// Use this as a constructor:
friend Lit mkLit(Var var, bool sign);
bool operator == (Lit p) const { return x == p.x; }
bool operator != (Lit p) const { return x != p.x; }
bool operator < (Lit p) const { return x < p.x; }
};
现在,我遇到了一个新问题:为
Lit
定义原型(prototype)时,尚未知道mkLit()
。因此,我需要对
Lit
进行前向声明并最终得到:#include <iostream>
typedef int Var;
struct Lit;
Lit mkLit(Var var, bool sign = false);
struct Lit {
int x;
// Use this as a constructor:
friend Lit mkLit(Var var, bool sign);
bool operator == (Lit p) const { return x == p.x; }
bool operator != (Lit p) const { return x != p.x; }
bool operator < (Lit p) const { return x < p.x; }
};
inline Lit mkLit(Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; }
int main()
{
Lit lit2 = mkLit(123, false);
std::cout << "lit2.x: " << lit2.x << '\n';
return 0;
}
输出:
Start
lit2.x: 246
0
Finish
Live Demo on wandbox
问题已解决。
我必须承认,我不确定
g++
是否接受原始版本(虽然不应该接受)或clang
是否拒绝原始版本(尽管不应该)。我的肚子感觉倾向于前者(即clang
是正确的)...在再次考虑
g++
中会发生什么之后,我得出的结论是它可以执行以下操作:friend Lit Lit::mkLit()
(从未使用过)Lit mkLit()
。 为了找出我将“
struct Lit
”“转换”为class Lit
,这也给g++
带来了错误:#include <iostream>
typedef int Var;
class Lit {
int x;
// Use this as a constructor:
friend Lit mkLit(Var var, bool sign = false);
bool operator == (Lit p) const { return x == p.x; }
bool operator != (Lit p) const { return x != p.x; }
bool operator < (Lit p) const { return x < p.x; }
};
inline Lit mkLit(Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; }
int main()
{
Lit lit2 = mkLit(123, false);
std::cout << "lit2.x: " << lit2.x << '\n';
return 0;
}
输出:
g++ (GCC) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
main.cpp: In function 'int main()':
main.cpp:17:35: error: 'int Lit::x' is private within this context
std::cout << "lit2.x: " << lit2.x << '\n';
Live Demo on coliru
因此,OP的原始版本仅适用于
g++
,因为带有公共(public)struct Lit
的int Lit::x
根本不需要friend Lit::mkLit()
。现在,我有点困惑。哪个是正确的
g++
或clang
?我不知道。关于c++ - 为什么结构需要 friend 功能?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52369155/