1

下面是一些旨在显示何时覆盖虚拟方法的代码。它输出: B B A A B A 这是正确的吗?我认为 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

4 回答 4

2

I don't see anything wrong:

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

You declare and initialize an instance of B, compile type is B, runtime type is B. Polymorphism is not needed (nor it can be achieved, since there is no pointer involved).

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

You declare a pointer to A and initialize it with an instance of A. Polymorphism works even if it is not necessary in this case, so foo() and bar() from A are called.

A * pA2 = &b;
pA2->foo(); pA2->bar();

You declare a pointer to A and initialize it with a reference to B. Compile time type is A*, runtime type is B*. Polymorphism through virtual function is applied, so the virtual method is B::foo() while the non-virtual is A::bar()

于 2013-10-01T02:38:21.370 回答
1

b.foo() gives B,

b.bar() also gives B which hides A::bar(). It is not overriding, it is name hiding.

pA->foo() gives A, pA->bar() gives A,

pA2->foo() gives B since it is a virtual function.

pA2->bar() gives A since it is not a virtual function. It is statically linked and it calls A::bar().

于 2013-10-01T02:36:47.000 回答
1

The first two outputs should both be B because you are calling foo() and bar() on an object of type B. Since you're not using a pointer, the compiler knows it's an object of type B and therefore does not need to consult the vtable to invoke the method, so even though bar() is not virtual, the compiler knows to use the B implementation.

The next two outputs should both be A because you're calling foo() and bar() on a pointer to an object of type A. In this case, foo() is virtual, and the vtable is pointing to the A implementation of the method. bar() is not virtual, so the compiler decides to use the A implementation.

The final two outputs should be B and A because you're calling foo() and bar() on a pointer to an object of type B. In this case, foo() is virtual, and the vtable is pointing to the B implementation of the method. bar() is not virtual, so the compiler decides to use the A implementation since you're using a pointer to an object of type A.

于 2013-10-01T02:37:46.457 回答
0

这是正确的, pA2->bar() 调用没有被覆盖。即使它是一个 B 对象,您也可以将其转换为 A 并且编译器会为 A 类调用 A 成员函数。

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

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

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

于 2013-10-01T02:47:38.143 回答