0

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 中的“{}”

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

谢谢您的回答 :)

4

1 回答 1

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;
};

我不知道你有什么编译器版本,所以不知道它是否支持非静态数据成员初始化(或者相同的修复是否适合你),但如果支持,那么这是你可能考虑的第五个解决方法因为它的意图是明确无误的。

删除constexpr对错误没有影响。

在您找到第三种解决方法的 3 种解决方法中,用A::A()显式替换默认A::A(){}值是唯一一种不会与您的班级所需的公共行为混淆的方法。

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

如果在现实世界中您有特定的理由声明A::A() as constexprthen 请记住,对于第三种解决方法,如果constexpr 构造函数不是default-ed,则 C++11 标准第 7.1.5 节第 4 段会放置相当繁琐的约束在构造函数及其类上,这可能会使您的代码在维护中更加脆弱。面对面的第五个解决方法的另一个可能的优点。

于 2013-08-01T08:48:41.247 回答