【问题标题】:inherited protected defaulted constructor is not accessible继承的受保护的默认构造函数不可访问
【发布时间】:2013-08-01 21:19:17
【问题描述】:

3尝试使用 ICC 编译以下代码会返回此错误: 错误 #453:受保护的函数“A::A()”(在第 10 行声明)不能通过“A”指针或对象访问。

class A
{
protected:
    constexpr A() = default;
    ~A() = default;

    A(const A&) = delete;
};

class B
    : protected A
{
public:
    B() = default;
};

int main()
{
    B b;
}

我发现了 3 种奇怪的方法让它可编译:

  • 公开 A 的 ctor
  • 删除 A 的已删除副本 ctor
  • 替换“=默认值;”通过 A 的 ctor 中的“{}”

我的意思是,为什么...?

感谢您的回答:)

【问题讨论】:

  • 这看起来像一个编译器错误,因为代码完全有效并且可以在其他编译器上编译。如果还没有发生,您可能需要提交错误报告。似乎有几个特征足以使编译器混淆以产生错误。为了完整起见,您能否尝试以下方法来缩小错误范围:1 删除 constexpr,2 尝试公共和私有继承,3用 B 的 ctor 3b 中的 {} 替换 = default 在 B 的 ctor 中显式初始化 A。 ICC 的有趣行为 :-)
  • 1、2 和 3 也不能编译,但是 3b 可以。

标签: c++ inheritance default-constructor icc


【解决方案1】:

我在 v13.1.3 (Linux) 上确认了这种不当行为。这当然是 Arne Mertz 所说的编译器错误:我发现如果 A 是 简单地提供了一个初始化的无意义的数据成员 在声明时,类编译,例如

class A
{
protected:
    constexpr A() = default;
    ~A() = default;

    A(const A&) = delete;

private:
    char placate_intel_compiler_bug = 0;
};

我不知道你有什么编译器版本,所以不知道 如果它支持非静态数据成员初始化(或者如果相同 fix 对你有用),但如果它确实如此,那么这是你的第 5 个解决方法 可能会考虑其意图明确无误的优点。

删除constexpr 对该错误没有影响。

在您找到的 3 种解决方法中,第三种是替换 默认A::A() 带有显式A::A(){} 是唯一的 这不会影响您班级所期望的公开行为。

Arne Mertz 的 3b 也适用于我,但它的缺点是 将解决方案放在课堂之外A

如果在现实世界中您有特殊原因声明 A::A() 作为constexpr,请记住,对于第三种解决方法,如果constexpr 构造函数不是default-ed 然后是 C++11 标准§ 7.1.5,第 4 段, 对构造函数及其类施加了相当繁琐的约束 使您的代码在维护中更加脆弱。另一个可能的加分项 用于面对面的第 5 种解决方法。

【讨论】:

  • 我在这里报告了这个错误,因为我不知道在哪里做:link。我认为数据成员解决方案是保持 A::A() 的编译行为的最佳方式。即使它消耗更多内存,这个不可复制的基类也只用于大对象。
  • 该链接是我相信 Joe Public 可以报告错误的正确(也是唯一)地方。由于它是专有工具链,因此他们没有开放的错误跟踪系统。
猜你喜欢
  • 2016-04-07
  • 2015-08-12
  • 2017-01-12
  • 2011-05-02
  • 2019-08-24
  • 2010-09-17
  • 2011-05-20
相关资源
最近更新 更多