【问题标题】:从类派生的结构的初始化列表(C++)
【发布时间】:2022-01-21 21:28:12
【问题描述】:

你能告诉我下面的例子有什么问题吗?我正在使用 C++17,我认为应该支持以下内容。

class Base {
public:
    virtual ~Base() = default;
};

struct Derived : public Base {
    int m1;
};

int main() {
    /* Results in a compilation error 
     * error C2440: 'initializing': cannot convert from 'initializer list' to 'Derived'
     * message : No constructor could take the source type, or constructor overload resolution was ambiguous */
    Derived d{ {},1 };
    return 0;
}

【问题讨论】:

  • Derived 不是聚合,因为它有一个带有虚拟成员的基类。所以它不能被初始化为一个聚合。
  • 移除 Base 中的虚拟析构函数确实会导致同样的编译错误,为什么会这样? (我想这将是一个危险的解决方案......)
  • 您使用哪个版本的 MSVC?您是否尝试过显式设置 C++17 模式 (/std:c++17)?
  • 谢谢,现在可以使用了!我需要添加 set(CMAKE_CXX_STANDARD 17)set(CMAKE_CXX_STANDARD_REQUIRED ON) 以将其显式设置为 C++ 17 并删除 Base 中的虚拟析构函数。我将使用 Derived 的 shared_ptrs 并将它们作为 Base 的 shared_ptrs 传递。我想为此我需要明确地实现一个构造函数来使用初始化列表?
  • 其实你不需要需要std::initializer_list构造函数。如果您声明一个,编译器应该选择正确的构造函数。然后你不需要在d的定义中初始化基类:Derived d{1};(带有合适的Derived(int)构造函数)就足够了。

标签: c++ inheritance struct initializer-list


【解决方案1】:

它不起作用,因为Derived 不是聚合,因为它有一个带有虚拟成员的基类。

当删除Base中的虚拟析构函数并使用C++17时,代码编译并运行。

如果Base 需要虚拟析构函数,Derived 可以实现自定义构造函数,允许使用大括号进行初始化。

class Base {
public:
    virtual ~Base() = default;
};

struct Derived : public Base {
    Derived(int m): m1(m) {}
    int m1;
};

int main() {
    Derived d{ 1 };
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2015-10-23
    • 2011-05-11
    相关资源
    最近更新 更多