C++20中Clang拒但GCC、MSVC接受的继承程序,哪个编译器合规?
C++20继承构造函数的编译器行为疑问
问题背景
以下代码在C20标准下被Clang编译器拒绝,但可被GCC和MSVC正常编译;在C17标准下所有编译器均拒绝编译。
示例代码
#include <array> #include <iostream> class Base { private: int data; public: Base(int pdata):data(pdata) {} Base(const Base&){std::cout <<" Copy base"; } }; class Derived : public Base { }; int main() { Derived d(1); // 被Clang拒绝,但GCC和MSVC接受 }
Clang的错误信息
<source>:19:12: error: no matching conversion for functional-style cast from 'int' to 'Derived' Derived d(1);
疑问
- 在C++20中哪个编译器的行为符合标准?
- 该程序在C++20中是否属于良构代码?
- 相关的C++标准变化是什么?
解答
1. 符合标准的编译器行为
GCC和MSVC的行为符合C++20标准,Clang的编译错误属于实现缺陷。
2. 程序在C++20中的合法性
该程序是良构代码。
3. 相关的C++20标准变化
核心变化是C++20调整了聚合类的构造规则以及基类构造函数的隐式继承逻辑:
- 在C++17及更早版本中,聚合类不能包含基类,且即使派生类没有声明任何构造函数,基类的构造函数也不会被隐式继承到派生类中。因此
Derived d(1);会因找不到匹配的Derived构造函数而编译失败。 - C++20允许聚合类继承基类(只要满足聚合类的其他条件:无用户声明的构造函数、无私有/保护的非静态数据成员、无虚函数等),并且当基类存在合适的构造函数时,派生类对象可以直接使用基类构造函数的参数列表进行初始化——编译器会自动将初始化操作转发给对应的基类构造函数。
在示例代码中,Derived是一个聚合类(无用户声明的构造函数、无额外数据成员等),因此它隐式继承了基类Base的Base(int)构造函数,Derived d(1);的初始化操作会被转发给Base的int参数构造函数,完全符合C++20标准。
内容的提问来源于stack exchange,提问作者user20562802
相关产品推荐
相关产品推荐

