1

在将私有成员作为参数传递给所有者的类函数时,通过聚合初始化来初始化私有成员是否正确?只需看下面的代码。

class A {
  struct S {
    int t, u;
  };
public:
  void f(const S& s) {}  
};

int main() {
  A a;
  a.f({1, 2}); // correct?
  return 0;
}

我检查了标准和网络,似乎没有确切的答案。看起来机制如下: * 大括号初始化程序是公共的,因此用户不会违反访问限制。* 从初始化程序到“S”的隐式转换对于“S”是内部的,因此对于编译器也很好。

问题是,标准、草案或至少 cppreference 中是否有对此行为的描述的参考?

4

2 回答 2

2

是的,这是正确的。唯一私密的S就是名字。访问控制仅通过名称([class.access]p4)控制访问。因此,您可以使用类型特征S通过f's type ( example ) 获取 example 的类型。

因此,它是允许的,因为没有限制[dcl.init.agg]禁止初始化“私有”类型。

还有一个注释,由@StephaDyatkovskiy 找到。

于 2019-05-14T08:17:10.793 回答
-1

它是否正式有效并不重要;你应该避免这种极端情况。

我会声称“它是有效的 C++”是错误的问题。

当您查看一段代码并尽可能尝试时,您无法确定它是否应该是有效的 C++;而且您知道这将是一些极端情况,具体取决于标准的确切措辞 - 无论哪种方式,不依赖该极端情况通常是个好主意。为什么?因为其他人也会感到困惑;他们会浪费时间试图弄清楚你的意思;他们会在标准中查找它——或者更糟的是,不查找它,并做出无效的假设;他们会从他们真正需要关注的事情上分心。

所以,有了这段代码,我会问自己:“类型S真的是私有的吗?外部代码真的不需要知道它吗?”

如果答案是“是的,它是”-那么我会更改f, 以获取 S 构造函数的参数(并将它们转发给 ctor):

void f(int t, int u) { S {t, u}; /* etc. etc. */ }

如果答案是“不,代码调用f()可以知道它正在传递一个S引用”——那么我会S公开。

于 2019-05-14T08:24:35.413 回答