覆盖非虚方法?

时间:2013-10-01 02:30:04

标签: c++ inheritance virtual

下面是一些代码,用于显示重写虚拟方法的时间。它输出: 乙 乙 一个 一个 乙 一个 它是否正确?我认为bar方法不能被覆盖......?

#include <iostream>
using namespace std;


class A
{
public:
    virtual void foo(){cout<<"A"<<endl;}
            void bar(){cout<<"A"<<endl;}
};

class B : public A
{
public:
    void foo(){cout<<"B"<<endl;}
    void bar(){cout<<"B"<<endl;}
};

int main()
{
    B b;
    A * pA = new A;
    A * pA2 = &b;
    b.foo(); b.bar();
    pA->foo(); pA->bar();
    pA2->foo(); pA2->bar();

}    

4 个答案:

答案 0 :(得分:2)

我没有看到任何错误:

B b;
b.foo(); b.bar();

您声明并初始化B的实例,编译类型为B,运行时类型为B。不需要多态性(因为没有涉及指针,所以也无法实现)。

A * pA = new A;
pA->foo(); pA->bar();

您声明指向A的指针,并使用A的实例对其进行初始化。即使在这种情况下没有必要,多态性仍然有效,因此调用来自foo()的{​​{1}}和bar()

A

您声明指向A * pA2 = &b; pA2->foo(); pA2->bar(); 的指针,并使用对A的引用对其进行初始化。编译时间类型为B,运行时类型为A*。应用通过虚函数的多态性,因此虚拟方法为B*,而非虚拟方法为B::foo()

答案 1 :(得分:1)

b.foo()提供B

b.bar()也会B隐藏A::bar()。它不是压倒性的,它隐藏着名字。

pA->foo()提供ApA->bar()提供A

pA2->foo()提供B,因为它是虚函数。

pA2->bar()给出A,因为它不是虚函数。它是静态链接的,并调用A::bar()

答案 2 :(得分:1)

前两个输出应该都是B,因为你在类型B的对象上调用foo()和bar()。因为你没有使用指针,编译器知道它是B类型的对象,因此不需要查阅vtable来调用方法,所以即使bar()不是虚拟的,编译器也知道使用B实现。

接下来的两个输出都应该是A,因为你在指向类型A的对象的指针上调用foo()和bar()。在这种情况下,foo()是虚拟的,而vtable指向该方法的实现。 bar()不是虚拟的,因此编译器决定使用A实现。

最后两个输出应该是B和A,因为你在指向类型B的对象的指针上调用foo()和bar()。在这种情况下,foo()是虚拟的,而vtable指向方法的B实现。 bar()不是虚拟的,因此编译器决定使用A实现,因为您正在使用指向A类对象的指针。

答案 3 :(得分:0)

这是正确的,不会覆盖pA2-&gt; bar()调用。即使它是一个B对象,也可以将它转换为A,编译器调用A类的成员函数。

foo()是虚拟的,因此包含在类B中的是指向哪个版本的foo()对于类是正确的指针,无论它被转换到何处。

此包含称为指向虚函数表的指针。只要您的类具有虚拟成员,就会为其创建一个静态函数表(并且还将包括任何其他后续虚函数),另外一个常量隐藏成员指针指向该表。当您转换对象时,函数表不会更改,任何虚函数都将保持“附加”到原始类型。

PS,别忘了删除pA ...你目前有内存泄漏:)