2015-09-06 70 views
0

我希望标题不会混淆。我试图理解下面的问题,这是由于在C++中定义一个虚拟类的方法而引起的。想象我有一个基类A和派生类B,使得编译时和运行时虚拟和非虚函数(C++)

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" 

然而,如果我声明这两类虚拟“打印”的方法,我反而看到“B”在我的屏幕打印。为什么这发生了?

+1

你能澄清一下问题:“为什么这是完全发生?”您是否要求在标准中指定语言的指定位置,或者您要求“什么是虚拟桌面,在典型的实现中它是如何工作的” –

+0

@ChrisBeck我知道问题的答案是,如果方法不是虚拟的,那么调用的方法“取决于编译时使用的类型”,而如果方法是虚拟的,那么“对象的运行时类型”决定调用哪个定义。这是我没有得到的。 – Adam

+0

可能的重复[为什么我们需要C++中的虚拟方法?](http://stackoverflow.com/questions/2391679/why-do-we-need-virtual-methods-in-c) –

回答

1

如果函数不是virtual,编译器将只使用表达式提供的任何类型。因此,当您将B对象投射到A对象时,它将调用A::print函数。

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

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

1

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

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

如果打印是Virttual /不实funtion:
编译时间:A.print()被绕过,B.print决心转到工作 运行:B.print()部署/分赴工作。