C++ 编译时和运行时期间的虚拟函数和非虚拟函数(C+;+;)

C++ 编译时和运行时期间的虚拟函数和非虚拟函数(C+;+;),c++,runtime,virtual-functions,compile-time,C++,Runtime,Virtual Functions,Compile Time,我希望标题不要混淆。我试图理解以下问题:C++中定义一个类的方法。假设我有一个基类a和一个派生类B,这样 class A { public: void print() { cout << "A"; } } class B : A { public: void print() { cout << "B"; } } 但是如果我将这两个类中的“print”方法声明为virtual,我会看到屏幕上打印出一个“B”。为什么会发生这种情况?如果函数不是虚拟

我希望标题不要混淆。我试图理解以下问题:C++中定义一个类的方法。假设我有一个基类a和一个派生类B,这样

class A { 
public:
    void print() { cout << "A"; } 
}

class B : A { 
public:
    void print() { cout << "B"; } 
}

但是如果我将这两个类中的“print”方法声明为virtual,我会看到屏幕上打印出一个“B”。为什么会发生这种情况?

如果函数不是虚拟函数,编译器只会使用表达式给出的任何类型。因此,当您将
B
对象强制转换为
a
对象时,它将调用
a::print
函数

如果您使用
virtual
,编译器将构建一个函数指针表[1],当调用函数时,编译器将生成通过该表调用的代码,而不仅仅是查看当前类型,这允许基类型调用派生类中的函数,从而允许多态行为

[1] 从技术上讲,规范没有告诉我们如何实现这一点,但几乎所有编译器都是这样工作的。如果编译器可以使用magic产生相同的行为,则允许它这样做-只要magic可靠且可复制。

A*b=new b()//LHS是编译时=RHS是运行时(因为“对象”是在运行时创建的)
B.打印()

如果打印是非虚拟的
编译时:A.print()被解析为转到工作状态(因为它是一个实函数)
运行时:A.print()被部署/分派到工作状态。

如果打印是虚拟/非真实功能:
编译时:a.print()被绕过,B.print被解析为继续工作
运行时:B.print()已部署/分派工作。

您能否澄清“为什么会发生这种情况?”您是否要求在标准中引用指定用于执行此操作的语言,或者您是否询问例如“什么是vtable,这在典型实现中实际如何工作?”@ChrisBeck我知道这个问题的答案是,如果方法不是虚拟的,那么调用的方法“取决于编译时使用的类型”,而如果方法是虚拟的,那么“对象的运行时类型”决定调用哪个定义。这正是我没有得到的。可能发生的重复情况是使用旧式强制转换来访问私有基类;隐式转换不起作用,而不是
静态转换
重新解释转换
可能在实践中起作用,但会产生错误。
A *a = new A();
B *b = new B();
((A *)b)->print(); // this prints "A"