简体   繁体   English

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

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

It's a bit surprising to me that this program: 这个程序对我来说有点意外:

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

Gave me this error (gcc 4.4): 给我这个错误(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) (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)

I expected that attempting to call a pure function would give an explicit error, because it was declared as deleted, rather than an implicit error. 我期望尝试调用纯函数会产生显式错误,因为它被声明为已删除,而不是隐式错误。 Is there not a distinction in the standard between "function not in this translation unit," and "function not in any translation unit?" “不在此翻译单元中的功能”与“不在任何翻译单元中的功能”之间的标准是否有区别?

It should be noted that attempting to directly call a pure virtual is not addressed in §10.4. 应该注意的是,尝试直接调用纯虚拟在第10.4节中没有解决。

Pure virtual functions can have a body . 纯虚函数可以有一个正文 Therefore the error is a link error, because you fail to provide the body. 因此,错误是链接错误,因为您无法提供正文。

Mark a function pure virtual does not mean that the function will have no implementation. 标记一个函数纯虚拟并不意味着该函数将没有实现。 All it means is that classes which derive from yours must either override this specific member function, or remain abstract . 所有这意味着从您的派生类派生的类必须覆盖此特定成员函数,或保持抽象 In particular, it is perfectly legal to provide an implementation of a pure virtual function for classes that derive from yours to inherit and use. 特别是,为从您的继承和使用派生的类提供纯虚函数的实现是完全合法的。

That is why the presence (or absence) of an implementation cannot be detected until the linking stage: you could provide an implementation in a separate translation unit, so the compiler may not know of it. 这就是为什么在链接阶段之前无法检测到实现的存在(或不存在)的原因:您可以在单独的转换单元中提供实现,因此编译器可能不知道它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM