c++ - 为什么不能在编译时解决运行时多态性?

标签 c++ polymorphism

考虑:

#include<iostream>
using namespace std;

class Base
{
    public:
        virtual void show() { cout<<" In Base \n"; }
};

class Derived: public Base
{
    public:
       void show() { cout<<"In Derived \n"; }
};

int main(void)
{
    Base *bp = new Derived;
    bp->show();  // RUN-TIME POLYMORPHISM
    return 0;
}

为什么这段代码会导致运行时多态,为什么不能在编译时解决?

最佳答案

因为在一般情况下,不可能在编译时确定它在运行时的类型。您的示例可以在编译时解决(请参阅@Quentin 的回答),但可以构建无法解决的案例,例如:

Base *bp;
if (rand() % 10 < 5)
    bp = new Derived;
else
    bp = new Base;
bp->show(); // only known at run time

编辑:感谢@nwp,这是一个更好的案例。比如:

Base *bp;
char c;
std::cin >> c;
if (c == 'd')
    bp = new Derived;
else
    bp = new Base;
bp->show(); // only known at run time 

另外,根据 Turing's proof 的推论,可以证明在一般情况下 C++ 编译器在数学上不可能知道基类指针在运行时指向什么。

假设我们有一个类似 C++ 编译器的函数:

bool bp_points_to_base(const string& program_file);

它的输入是 program_file:any C++ 源代码文本文件的名称,其中指针 bp(如在 OP ) 调用它的 virtual 成员函数 show()。并且可以确定在一般情况下(在virtual成员函数show()首先出现的序列点A通过bp调用):指针bp是否指向Base的实例。

考虑以下 C++ 程序“q.cpp”的片段:

Base *bp;
if (bp_points_to_base("q.cpp")) // invokes bp_points_to_base on itself
    bp = new Derived;
else
    bp = new Base;
bp->show();  // sequence point A

现在如果 bp_points_to_base 确定在“q.cpp”中:bp 指向 ABase 实例code> 然后 "q.cpp"将 bp 指向 A 处的其他内容。如果它确定在“q.cpp”中:bp 没有指向 A 处的 Base 实例,那么“q. cpp"将 bp 指向 A 处的 Base 实例。这是一个矛盾。所以我们最初的假设是不正确的。所以bp_points_to_base不能写成一般情况

关于c++ - 为什么不能在编译时解决运行时多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34354516/

相关文章:

c++ - C 库链接到 C++

haskell - 我应该总是更喜欢更通用的类型而不是特定的类型吗?

ios - Objective-C 函数通过在方法签名中指定关系来更新 Core Data 关系

java - 为什么不允许重写方法中参数类型的差异(一个是原始方法,另一个是包装器)?

c++ - 为什么我的 C++ 程序在执行 tcmalloc heap-checker 或 heap-profile 时使用大量内存

c++ - 在 C++ 中将 base 16 字符串转换为 base 256 字符串,反之亦然

c++ - boost::system::error_category 处未解析的外部符号

c++ - 如何在linux中找到分配的内存

c++ - 是否可以根据需要继续向基类(接口(interface))添加虚方法?

c++ - 重载虚拟方法与非虚拟方法有何不同?