1

我正在尝试为从其父朋友类的子类继承的数据结构使用初始化列表。下面我编译了一个示例来演示该问题(在 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};

如果成员可以使用,为什么初始化列表会失败并出现编译错误?

4

1 回答 1

4

这两行并不等价,尽管两者都出现了相同的标识符。这个

i_have_secrets::i_have_secrets(){
    i_am_secret = {0, {0,1,2}}; // Totally fine
}

分配给类型为的成员变量secret_t。碰巧这是 C++11 中的聚合secret_t,所以它所做的是对分配给.secret_ti_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(not secret_t) 的对象。在 C++11 中,具有任何基类的类不是聚合。因此,尝试通过聚合初始化来初始化非聚合是行不通的。

您可以使用类型别名而不是派生类

class i_gossip{
public:
    using i_am_secret = i_have_secrets::secret_t;
};

这将暴露内部类型、聚合初始化和所有内容。

或者,您可以切换到 C++17,其中允许聚合具有公共基类。

于 2019-09-18T09:24:46.980 回答