从朋友类继承时无法使用大括号括起来的初始化列表
Posted
技术标签:
【中文标题】从朋友类继承时无法使用大括号括起来的初始化列表【英文标题】:Unable to use brace enclosed initializer-list while inheriting from friend class 【发布时间】:2019-09-18 09:12:06 【问题描述】:我正在尝试为从其父朋友类的子类继承的数据结构使用初始化列表。 下面我编译了一个演示问题的示例(在 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;
如果成员可以使用,为什么初始化列表会失败并出现编译错误?
【问题讨论】:
不能用 clang++(只给我一个警告,建议另一个大括号级别,i_gossip::i_am_secret secret = 0, 0,1,2;
)和 g++(没有错误也没有警告)复制。你用的是哪个编译器?
gcc 版本 9.2.0(Rev2,由 MSYS2 项目构建)与 -std=c++11
对不起:我已经编译了 C++17;是的:使用 C++11 和 C++14 我重现了你的错误。
【参考方案1】:
尽管两行出现相同的标识符,但这两行并不等价。这个
i_have_secrets::i_have_secrets()
i_am_secret = 0, 0,1,2; // Totally fine
分配给类型为secret_t
的成员变量。碰巧secret_t
是 C++11 中的聚合,所以它的作用是执行分配给 i_have_secrets::i_am_secret
的临时 secret_t
的 aggregate initialization。
另一方面,这条线
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 i_gossip
public:
using i_am_secret = i_have_secrets::secret_t;
;
这将暴露内部类型、聚合初始化和所有内容。
或者,您可以切换到 C++17,其中允许聚合具有公共基类。
【讨论】:
以上是关于从朋友类继承时无法使用大括号括起来的初始化列表的主要内容,如果未能解决你的问题,请参考以下文章