2014-01-20 48 views
0

我有了这个鳕鱼:C++虚函数意外行为

class First{ 
public: 
    virtual void print(){cout<<"First";} 

}; 

class Second : public First { 
public: 
    virtual void print(){cout<<"Second";} 


}; 
class Third : public Second{ 
public: 
    void print(){cout<<"Third";} 

    int main(){ 
    Third ob; 
    ob.print(); 
    Second& sec=ob; 
    sec.print(); 
    First& frs=ob; 
    frs.print(); 
} 

一切都将会如我所料,所有3打印:“第三”。

现在,因为我有太多的代码,它是基本相同的一点点改变,我会在文中讨论它。

现在我从First中删除虚拟打印,并按照我的预期打印出“Third Third First”。

这第三次,我把虚拟放在第一,但我从第二次删除它。现在它打印: “第三第三第三”。嗯,这不是我所期望的。可以这样说,当使用引用时首先它看到函数是虚拟的,然后检查对象并调用第三个方法,但是当引用第二个时,它看到该函数不是虚拟的,为什么它仍然调用Third的打印?

+0

因为您使用的是第三个对象的引用。即使你使用类型,运行时vtable仍然将其视为第三个 – Gasim

+5

“Second”中的函数是隐式虚拟的,因为它与First中的函数具有相同的签名。 – dyp

+0

请注意,当'Third'出现时,将'Second'中的'print'标记为'final'会给你一个明确的错误。 – chris

回答

4

如果一个函数覆盖了一个虚函数,那么它是虚拟的,不管你是否显式声明它。所以这里Second::print是虚拟的,但是你声明它。

3

函数被视为虚拟的,如果它被声明为虚拟的或者它在任何基类中被声明为虚拟的(当通过指针或引用调用时)。

0

预计最后一种情况下的行为。您正在使用对Third类型的对象的引用。所以这三个调用都会调用这个类的虚函数。您在类Second中删除了该函数的声明,但cvlass从First继承了此函数。它只是不覆盖它。