为什么调用纯虚拟链接器错误而不是编译错误?

Why is calling a pure virtual a linker error rather than a compile error?

这个程序让我有点惊讶:

struct A {
  virtual void a()=0;
};

struct B : public A {
  void a() {}
};

int main() {
  B b;
  b.a(); // OK, call B::a()
  b.A::a(); // linker error?
}

给我这个错误 (gcc 4.4):

/tmp/ccfOGuBJ.o: In function `main':
test.cc:(.text+0x28): undefined reference to `A::a()'
collect2: ld returned 1 exit status

(clang 7.0.0)

Undefined symbols for architecture x86_64:
  "A::a()", referenced from:
      _main in test-440cc5.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我预计尝试调用纯函数会给出显式错误,因为它被声明为已删除,而不是隐式错误。 "function not in this translation unit," 和 "function not in any translation unit?"

之间的标准没有区别吗?

应该注意的是,尝试直接调用纯虚拟并没有在§10.4 中解决。

纯虚函数can have a body。因此错误是 link 错误,因为您未能提供正文。

将函数标记为纯虚并不意味着该函数将没有实现。这意味着从你的派生的 类 必须覆盖这个特定的成员函数,或者保持 抽象 。特别是,为 类 提供纯虚函数的实现是完全合法的,该函数派生自您的函数以供继承和使用。

这就是为什么在链接阶段之前无法检测到实现的存在(或不存在)的原因:您可以在单独的翻译单元中提供实现,因此编译器可能不知道它。