是否有任何原因无法在编译时解决覆盖问题。
假设你正在谈论多态性,即
#include <iostream>
class Base
{
public:
virtual void Foo()
{
std::cout << "Base::Foo()" << std::endl;
}
};
class Derived : public Base
{
public:
virtual void Foo()
{
std::cout << "Derived::Foo()" << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
上面的代码允许这样的事情按预期工作:
void CallFoo(Base& b)
{
b.Foo();
}
int main()
{
Base b;
Derived d;
CallFoo(b); // calls Base::Foo()
CallFoo(d); // Calls Derived::Foo();
}
Run Code Online (Sandbox Code Playgroud)
重要的是要认识到CallFoo()
对实际是什么一无所知b
(它可能指的是一个Base
实例或一个Derived
实例)。所有CallFoo()
gets 都是对 的引用Base
,它没有告诉任何它实际引用的内容,因此编译器无法在编译时知道它是什么CallFoo()
。因此,确定是否Base::Foo()
或Derived::Foo()
应该被调用必然是运行时的决定。
删除virtual
关键字(以禁用覆盖)将导致上面的代码打印Base::Foo()
两次,而不是Base::Foo()
then Derived::Foo()
。这是因为如果没有关键字,编译器将简单地在编译时virtual
解析对的调用。Base::Foo()
话虽如此,由于虚拟函数会产生一些开销(毕竟,需要调用的正确函数是运行时决定的),因此编译器将尽力找出 in 的实际类型(b
如果CallFoo()
可以的话)。在这种情况下,它就成为编译时决定。然而,这是一个实施细节。