为什么C++花括号初始化不支持私有成员聚合体?

4
从概念上看,我认为以下内容不会侵犯隐私。但是它是被禁止的。
struct A
{
        int a;
        int b;
        int c;
};
struct B
{
        int a;
        int b;
private:
        int c;
};

int main (int argc, char * argv[])
{
        auto a = A{1,2,3}; //ok
        auto b = A{1,2};   //ok
        auto c = B{1,2,3}; //error
        auto d = B{1,2};   //error
        return 0;
}

添加一个手动构造函数可以允许对私有成员使用大括号初始化。但聚合体和 POD 的美妙之处在于你只需要很少的编码,因此这很麻烦。

另一方面,在我看来,这是一种隐私泄露,但这是标准允许的。


3
不能对struct B使用聚合初始化,因为它不是一个聚合类型(所有非静态成员变量必须是公有的才能构成聚合类型)。 - Jerry Coffin
@Jerry,是的,我知道,这就是我说的。但我也在抱怨。为什么标准要把本来可以很简单的事情搞得那么复杂呢? - Patrick Fromberg
1
你基本上在问为什么类的非成员不能写私有变量。这是设计上的限制。链接的问题是一个边角情况,可以说是标准缺陷。 - GManNickG
1
@GMan。为什么将大括号初始化视为非成员访问?对我来说,它有点类似于构造函数调用。这是一种新的自动构造函数。 - Patrick Fromberg
1
当前的规则非常简单明了。如果允许对具有私有成员的对象进行聚合初始化,那么像 class A { int a; public: int b; }; A a{1}; 这样的情况该如何处理呢?你会使用 1 来初始化 A::a 还是 A::b 呢?无论哪种选择都会让很多人感到不满和困惑。 - Jerry Coffin
2个回答

6

聚合体中不存在私有或受保护的非静态数据成员。聚合体的所有非静态数据成员必须是公共的。

private:
    int c;

导致B不再是一个聚合体,因此聚合初始化将无法正常工作。


答案是正确的,我的问题不是因为我想知道标准为什么做出了这个限制。 - Patrick Fromberg

0
Jerry Coffin是正确的,我认为。该类没有权力禁止其私有/受保护成员被客户端初始化为任何值或未经其假设的“聚合初始化”初始化。

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接