多态或遗传?

时间:2012-02-14 12:55:12

标签: c++ inheritance polymorphism

我有一个关于C ++的理论问题。这是我大学期末考试的一部分,我想知道为什么调用类f的方法B,而它应该由基类A派生。既然不是虚拟的,不应该调用A :: f()吗?

#include <iostream.h>
#include <stdlib.h>

class A{
     public:int f(int x){
               cout<< x << " ";
     }
};
class B:public A{
     public:int f(int y){
                A::f(y+1);
     }
};
void g(A a, B b) {
       a.f(3);
       b.f(3);
 }

int main()
{
  B p; 
  B q; 
  g(p,q);
  system("PAUSE");
  return 0;
}

// result is 3 4

5 个答案:

答案 0 :(得分:2)

bg()的静态类型是B,因此这里不需要虚拟 - 编译器可以知道[在编译时]你要调用{{1这正是他正在做的事情。
在这里,课程B::f()重新定义了B的{​​{1}}并隐藏了它,因此从静态类型为{{1}的变量调用A }导致调用f()

请注意,f()关键字允许您使用覆盖方法,其中静态类型是父类型。

答案 1 :(得分:2)

方法g有两个参数,类型为AB。由于这些不是指针或引用类型,因此动态绑定不适用。编译器在编译时知道对象的实际类型,并进行静态方法调用。

virtual方法仅适用于指针或引用!

答案 2 :(得分:1)

int f(int)中的函数B“隐藏”其基类中具有相同名称和签名的函数。

因此,当您致电b.f(3);并且变量b的类型为B时,您正在调用B::f

只有在{em>变量 b.f(3)的类型为B::f的情况下,b才能调用A&,才需要虚拟函数,但它引用的对象具有运行时类型B。在这种情况下,如果B::f是虚拟的,则调用的函数将为A::f,如果为非虚拟,则调用A::f

虚函数调用将对象的运行时类型考虑在内,即使它们是通过指针或对基类的引用使用的。但B b; b.f(3)是对B::f的调用,无论A::f是否存在,都不管它是虚拟的还是非虚拟的。

答案 3 :(得分:0)

“非科学”解释:

函数g a视为A的实例 获取p的副本作为对象类型为A(请参阅下面的评论),并在f内执行Ab被视为B的实例,其中方法B.f会覆盖A.f,因此当b被“查看”为B的实例时1}}我们执行b.f,方法B.f将被执行,因为A.f不可见

如果您想使用A.f致电b.f,则必须将b投放到A((A)b).f()

答案 4 :(得分:0)

这里发生了两件事:

  1. 你正在切割你的物体。
  2. 您的f()函数不是覆盖,因为它不是虚拟的,实际上您不应该这样做。
  3. 您可以通过使函数g通过引用获取其第一个参数来克服切片。如果给A一个受保护的拷贝构造函数也会阻止它,尽管那时你将无法复制A的真实实例。

    在这种情况下,即使参考A,函数g也总是会调用A::f(),因为没有多态性。要调用它,您需要将A::f()声明为虚拟。