编译时和运行时的虚函数和非虚函数(C ++)

时间:2015-09-06 22:40:53

标签: c++ runtime virtual-functions compile-time

我希望标题不会混淆。我试图理解在C ++中定义类虚拟或非虚拟方法时出现的以下问题。想象一下,我有一个基类A和一个派生类B,例如

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

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

如果我知道执行下面的代码,打印命令将打印出“A”。

A *a = new A();
B *b = new B();
((A *)b)->print(); // this prints "A"

然而,如果我将两个类中的“print”方法声明为虚拟,我会在屏幕上看到“B”。为什么会发生这种情况?

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

A * b =新B(); // LHS是编译时间= RHS是运行时(coz'对象是在运行时创建的)
B.print();

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

如果打印是Virttual /非实际功能:
编译时间:绕过A.print()并解决B.print解决工作 runtime:B.print()被部署/分派工作。