从朋友 class 继承时无法使用大括号括起来的初始值设定项列表
Unable to use brace enclosed initializer-list while inheriting from friend class
我正在尝试为从其父朋友 class 的子 class 继承的数据结构使用初始化列表。
下面我编译了一个演示问题的示例(在 c++11 中)。
#include <iostream>
#include <vector>
class i_gossip;
class i_have_secrets{
friend class i_gossip;
public:
i_have_secrets();
private:
struct secret_t{
int secret_number;
std::vector<int> secret_vector;
}i_am_secret;
};
class i_gossip{
public:
struct i_am_secret : public i_have_secrets::secret_t { };
};
i_have_secrets::i_have_secrets(){
i_am_secret = {0, {0,1,2}}; // Totally fine
}
int main(int argc,char** args){
i_gossip::i_am_secret secret = {0, {0,1,2}}; // Compile error
return 0;
}
声明没问题,初始化不行,报错could not convert {...} from '<brace-enclosed initializer list>' to i_gossip::i_am_secret secret
。可以通过这样寻址和设置结构的每个成员来编译程序:
i_gossip::i_am_secret secret;
secret.secret_number = 0;
secret.secret_vector = {0,1,2};
如果成员可用,为什么初始化列表会因编译错误而失败?
这两行并不等同,尽管两行中出现了相同的标识符。这个
i_have_secrets::i_have_secrets(){
i_am_secret = {0, {0,1,2}}; // Totally fine
}
赋值给类型为secret_t
的成员变量。碰巧 secret_t
是 C++11 中的聚合,所以它所做的是执行 aggregate initialization 临时 secret_t
分配给 i_have_secrets::i_am_secret
.
另一方面,这一行
int main(int argc,char** args){
i_gossip::i_am_secret secret = {0, {0,1,2}}; // Compile error
return 0;
}
尝试初始化类型为 i_gossip::i_am_secret
(而非 secret_t
)的对象。在 C++11 中,具有任何基数 class 的 class 不是聚合。因此,通过聚合初始化来初始化非聚合的尝试是行不通的。
您可以使用类型别名而不是派生的 class
class i_gossip{
public:
using i_am_secret = i_have_secrets::secret_t;
};
这将公开内部类型、聚合初始化和所有内容。
或者,您可以切换到 C++17,其中聚合允许具有 public base classes.
我正在尝试为从其父朋友 class 的子 class 继承的数据结构使用初始化列表。 下面我编译了一个演示问题的示例(在 c++11 中)。
#include <iostream>
#include <vector>
class i_gossip;
class i_have_secrets{
friend class i_gossip;
public:
i_have_secrets();
private:
struct secret_t{
int secret_number;
std::vector<int> secret_vector;
}i_am_secret;
};
class i_gossip{
public:
struct i_am_secret : public i_have_secrets::secret_t { };
};
i_have_secrets::i_have_secrets(){
i_am_secret = {0, {0,1,2}}; // Totally fine
}
int main(int argc,char** args){
i_gossip::i_am_secret secret = {0, {0,1,2}}; // Compile error
return 0;
}
声明没问题,初始化不行,报错could not convert {...} from '<brace-enclosed initializer list>' to i_gossip::i_am_secret secret
。可以通过这样寻址和设置结构的每个成员来编译程序:
i_gossip::i_am_secret secret;
secret.secret_number = 0;
secret.secret_vector = {0,1,2};
如果成员可用,为什么初始化列表会因编译错误而失败?
这两行并不等同,尽管两行中出现了相同的标识符。这个
i_have_secrets::i_have_secrets(){
i_am_secret = {0, {0,1,2}}; // Totally fine
}
赋值给类型为secret_t
的成员变量。碰巧 secret_t
是 C++11 中的聚合,所以它所做的是执行 aggregate initialization 临时 secret_t
分配给 i_have_secrets::i_am_secret
.
另一方面,这一行
int main(int argc,char** args){
i_gossip::i_am_secret secret = {0, {0,1,2}}; // Compile error
return 0;
}
尝试初始化类型为 i_gossip::i_am_secret
(而非 secret_t
)的对象。在 C++11 中,具有任何基数 class 的 class 不是聚合。因此,通过聚合初始化来初始化非聚合的尝试是行不通的。
您可以使用类型别名而不是派生的 class
class i_gossip{
public:
using i_am_secret = i_have_secrets::secret_t;
};
这将公开内部类型、聚合初始化和所有内容。
或者,您可以切换到 C++17,其中聚合允许具有 public base classes.