C++重载和重写解析时间

Ale*_*Dan 3 c++ overriding

为什么重写是在运行时解决的,而重载是在编译时解决的?
是否有任何原因无法在编译时解决覆盖问题。

In *_*ico 5

是否有任何原因无法在编译时解决覆盖问题。

假设你正在谈论多态性,即

#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()可以的话)。在这种情况下,它就成为编译时决定。然而,这是一个实施细节。