Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;重载和重写解析时间_C++_Overriding - Fatal编程技术网

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

C++ c++;重载和重写解析时间,c++,overriding,C++,Overriding,为什么在运行时解决重写问题,而在编译时解决重载问题? 是否有任何原因导致无法在编译时解析重写 是否有任何原因导致无法在编译时解析重写 假设你说的是多态性,即 #include <iostream> class Base { public: virtual void Foo() { std::cout << "Base::Foo()" << std::endl; } }; class Derived : public

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

是否有任何原因导致无法在编译时解析重写

假设你说的是多态性,即

#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;
    }
};
重要的是要认识到,
CallFoo()
b
实际上是什么一无所知(它可能指的是
Base
实例或
派生的
实例)。所有
CallFoo()
获取的都是对
Base
的引用,它不告诉任何它实际引用的内容,因此编译器在编译
CallFoo()
时无法分辨它是什么。因此,确定是调用
Base::Foo()
还是调用
Derived::Foo()
,必然是一个运行时决策

删除
virtual
关键字(禁用覆盖)将导致上述代码打印两次
Base::Foo()
,而不是
Base::Foo()
然后
Derived::Foo()
。这是因为没有
virtual
关键字,编译器只需在编译时解析对
Base::Foo()
的调用


也就是说,由于虚拟函数会产生一些开销(毕竟,需要调用的正确函数是运行时决定),编译器将尽最大努力找出
CallFoo()中
b
的实际类型(如果可以)。在这种情况下,它将成为编译时决策。但是,这是一个实现细节。

重写只在虚拟函数运行时解决,因为这就是实现的方式。非虚拟函数调用在编译时解析。

为什么在运行时解析重写,而在编译时解析重载?

这实际上要视情况而定。
通常,编译器无法确定要调用的实际函数,直到运行时发生溢出时。这是因为基类指针指向的实际对象在运行时之前可能是未知的。在这种情况下,编译器别无选择,只能在运行时解析实际的函数调用。
然而,有时编译器可以智能地、决定性地检测需要调用的函数,即使是在溢出的情况下,在这种情况下,编译器也可以在编译时解析要调用的函数


在重载的情况下,编译器可以根据传递给函数的参数确定要调用的实际函数,因此编译器无需等到运行时才能解析此类调用,因为所有参数类型在编译时都是已知的,由于C++是静态类型的语言,所有类型都必须在编译时知道。C++中的

函数重载可以由编译器自己来处理。在函数重载期间,编译器“修饰”函数名,技术上称为
name mangling
。因此,在生成的代码中,每个重载方法都有一个单独的名称。这样,编译器知道在编译时自己调用哪个方法


在函数重写(派生类在其基类中重新定义方法)的情况下,如果基类方法是非虚拟的,那么调用哪个函数将在编译时确定。但若它是一个虚拟函数,那个么编译器就不能在编译时解析调用。必须通过对象中的虚拟指针进行虚拟表查找。这只能发生在运行时,因为只有在运行时,您才能知道您正在处理的对象。

有时编译器可以智能地、最终地检测到需要调用的函数,即使是在溢出的情况下。
您有这样的例子吗?@Jesse:Check out:,是的,我引用的是一个已经证实的事实。这里没有猜测。你告诉我们——如何在编译时解决重写问题?@ildjarn:你可能想检查我答案下注释中的链接。@Als:动态多态性被完全禁用的上下文(因此与问题/对话无关)这不是我想问的。显然,要使用多态性,必须在多态上下文中。
void CallFoo(Base& b)
{
    b.Foo(); 
}

int main()
{
    Base b;
    Derived d;
    CallFoo(b); // calls Base::Foo()
    CallFoo(d); // Calls Derived::Foo();
}