为什么结构需要朋友功能?

萨尔帕斯

我正在尝试构建一个程序程序是从Internet下载的。当我尝试编译它时,出现错误信息

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; }

我发现了几个可以解决此问题的问题,但问题相当深刻,我不太理解这些解释。这个问题答案表明,我可以通过以下方式解决问题:将mkLitstruct的内联定义移到struct之前,从友元函数声明中删除默认参数,然后将其移至内联定义。这个对吗?

但更简单地说,我不明白为什么结构需要朋友功能,因为它的成员无论如何都是公共的。这个问题的可接受答案给出了一个基于参数依赖的查询的答案(我的无知使我无法理解),但是我看不到它在这种情况下适用。

仅删除好友函数声明并将默认参数移至内联函数定义是否有任何缺点?如果是这样,您能举一个简单的例子吗?

舍夫

我花了一段时间才知道,但最终我发现了。

因此,我忽略了误导性标题(用户463035818恕我直言已经充分回答了该问题),并专注于

friend declaration specifying a default argument must be the only declaration

引起了我的注意。

因此,friend由于我认为此错误涉及另一个问题,因此我不再重复已说过的内容和对公众成员的访问权限。

首先,我在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

在大肠杆菌上进行现场演示

嗯是的 运行良好。

然后我这次在wandbox上做了以下操作clang HEAD 8.0.0

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

魔盒上的现场演示

我们到了。

因此,我试图了解clang抱怨的地方。

最后,我发现了clangfinds,Lit Lit::mkLit()并且Lit mkLit()此后定义不匹配

可以通过mkLit()插入以下内容的原型来解决此问题struct Lit

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在定义proto时(尚不知道)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

魔盒上的现场演示

问题已解决。

我必须承认,我不确定是否g++接受原始版本(尽管不应该接受)或是否clang拒绝原始版本(尽管不应该接受)。我的肚子感觉倾向于前者(即clang是正确的)...


在再次考虑发生了什么之后g++,我得出的结论是它可以执行以下操作:

  1. 接受friend Lit Lit::mkLit()(从未使用过)

  2. 定义另一个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';

在大肠杆菌上进行现场演示

因此,OP的原始版本就可以使用了,g++因为struct Lit与publicint Lit::x完全不需要friend Lit::mkLit()

现在,我有点困惑。哪一个是正确的g++还是clang我不知道。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么HashiCorp的Vault需要启用ipc_lock功能?

“朋友结构A”和“朋友结构A”有什么区别?和“朋友A”;句法?

动态编程:为什么需要最佳子结构

为什么功能组合需要括号?

为什么clang拒绝可变参数模板的朋友功能

为什么Flow需要注释导出功能的参数?

为什么g ++同时需要模板类及其朋友函数的定义?

为什么在MISRA:2012中需要功能原型?

为什么列表结构中的某些功能需要“列表”前缀,而有些则不需要?

朋友功能为什么无法访问继承类的私有变量?

为什么此功能参数在元组上需要双括号?

为什么减少谓词功能需要包装器功能?

沿类层次结构的私有继承,为什么整个层次结构都需要朋友

指向结构的指针数组-为什么需要malloc(),为什么需要直接字段副本?

为什么定义MonadReader需要功能依赖?

朋友功能需要助手功能

为什么不能使用显式模板参数调用模板朋友功能?

为什么此功能需要将“ this”绑定到它?

为什么需要成为朋友才能访问受保护的成员?

Python OOP-为什么在功能中需要模块名称

为什么仅声明朋友功能不能具有默认参数?

为什么“查看”功能需要这么长时间才能运行?

如何在朋友功能内使用私有结构?

为什么需要在结构中填充?

为什么Java 8的功能样式结构称为“流”?

试图与Derived in Base的功能成为朋友-为什么它不起作用?

为什么我们需要 WalletApi 的“startWatching”功能?

为什么这个结构需要 24 个字节

有键盘驱动,为什么winapi功能需要扫码?