假设我有以下两个文件,main.cpp
:编译器如何知道要使用哪个catch块?
#include <iostream>
class A {};
void foo();
int main(void)
{
try {
foo();
}
catch(const A& e) {
std::cout << "Caught an A." << std::endl;
}
return 0;
}
和foo.cpp
:
class A {};
class B : public A {};
void foo()
{
B b;
throw b;
}
现在,当我单独编译每个文件,链接生成的目标文件,并运行结果可执行文件,我得到预期的结果:
$ clang++ --std=c++14 -c main.cpp
$ clang++ --std=c++14 -c foo.cpp
$ clang++ --std=c++14 main.o foo.o
$ ./a.out
Caught an A.
而这让我难以置信!类A
没有虚拟方法。因此,它不是多形的,它的实例在运行时不应携带任何类型信息。 main.o
目标文件不知道正在抛出什么,因为实际抛出发生在foo()
内部,其主体在单独的编译单元中定义。目标文件具有更多信息,但同样不了解任何捕获语句和捕获的异常的预期类型。
简而言之:我没有看到两个源文件分别编译然后链接如何生成上面的输入,而无需处理一些运行时类型信息。这两个文件分别编译应该有足够的信息来采取正确的catch块。
B是A的子类,因此您可以在B的任何实例上查看A的“透镜”。 – freestyle
为什么要重新定义“A类”? – Raindrop7
由于协变 – arturx64