即使基类和派生类都有公共数据成员
#include <iostream>
class M {
public:
int x = 2;
volatile double y=3;
};
class S:public M {
public:
int x1 = 4 ;
volatile double y1 = 5;
};
int main() {
S f();
S a;
std::cout<<a.x<<a.y<<a.x1<<a.y1;
auto [b,c,d,e] = f();
}
获取错误
auto [b,c,d,e] = f();
main.cpp:在函数'int main()'中:main.cpp:21:10:错误:不能 分解类类型'S':它和它的基类'M'都有 非静态数据成员 auto [b,c,d,e] = f();
根据http://en.cppreference.com/w/cpp/language/structured_binding
案例3:绑定到公共数据成员
E的每个非静态数据成员必须是E的公共直接成员或 的明确公共基础,
无法理解这是什么意思 同样明确的E 公共基础,
答案 0 :(得分:6)
&#34;同样明确的公共基础&#34;有效地意味着,在整个类层次结构中,只能有一个类,其中包含成员。
这有点像聚合初始化的前C ++ 17规则(仅在那里,它们明确禁止继承)。 C ++ 17允许基类聚合初始化,但结构化绑定(概念上是聚合初始化的反转)并没有得到备忘录。
答案 1 :(得分:4)
这里有三个形容词,它们指定了三个正交要求:
为了查看反例,可能会有所帮助。在所有情况下,假设template <class T> T make();
存在。
&#34;相同&#34;的反例:D
有两名成员,但他们不是D
的同一基数的成员 - i
是B
的成员,但j
是D
的成员:
struct B { int i; };
struct D : B { int j; };
auto [i, j] = make<D>(); // error
要解决此问题,j
需要成为B
的直接成员或i
需要成为D
的直接成员:
struct B { int i, j; };
struct D : B { };
auto [i, j] = make<D>(); // ok
struct B { };
struct D : B { int i, j; };
auto [i, j] = make<D>(); // ok
&#34;明确&#34;的反例:D
有两个成员,他们都是B
的成员,但它是D
的模糊基类{1}}。
struct B { int i; };
struct M1 : B { };
struct M2 : B { };
struct D : M1, M2 { };
auto [i, j] = make<D>(); // error
如果B
是[{1}}和virtual
的{{1}}基数,那么这样就可以了:
M1
&#34; public&#34;的反例。这是最简单的一个。如果成员在私人基地,他们无论如何都无法访问:
M2
另请注意,正如TC指出的那样,要求是 base 是公开的,而不是成员可访问。也就是说,从私人基地访问成员仍然无效:
struct B { int i; };
struct M1 : virtual B { };
struct M2 : virtual B { };
struct D : M1, M2 { };
auto [i] = make<D>(); // ok
当然,在所有这些反例中,仅仅因为所有成员都不在同一个,明确的公共基类struct B { int i; };
struct D : private B { };
make<D>().i; // error, as-is
auto [i] = make<D>(); // error, non-public base, but really same reason
并不意味着它对结构化绑定不可用。它只是意味着你必须自己写出绑定:
struct B { int i; };
struct D : private B { using B::i; };
make<D>().i; // ok now, due to the using-declaration
auto [i] = make<D>(); // still error, B is still private base