我希望标题不会混淆。我试图理解在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”。为什么会发生这种情况?
答案 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()被部署/分派工作。