繁体   English   中英

覆盖非虚方法?

[英]Overriding Non-Virtual methods?

下面是一些代码,用于显示重写虚拟方法的时间。 它输出:BBAABA这是正确的吗? 我以为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();

}    

我没有看到任何错误:

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

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

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

你声明的指针, A与实例初始化A 即使在这种情况下不需要多态性也可以工作,因此调用来自A foo()bar()

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

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

b.foo()给出B

b.bar()也给出了隐藏A::bar() B 它不是压倒一切,它隐藏着名字。

pA->foo()给出ApA->bar()给出A

pA2->foo()给出B因为它是一个虚函数。

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM