派生类中的虚拟函数,但基类中的非虚拟函数 [英] virtual function in derived class, but non-virtual in base class

查看:119
本文介绍了派生类中的虚拟函数,但基类中的非虚拟函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我正在运行以下多态性的C ++代码:

  class 基本
{
公共:
     虚拟  无效  f1 (){std: :cout<< " << std :: endl;}
    无效  f (){std :: cout<< " << std :: endl;}
};

 class 派生: public  Base
{
公共:
     虚拟  无效  f (){std: :cout<< " << std :: endl;}
};
 class  DDerived: public  Derived
{
公共:
     虚拟  无效  f (){std: :cout<< " << std :: endl;}
}; 


 基础 * p_base =  DDerived();
p_base->  f ();
派生 * p_derived =  DDerived();
p_derived->  f ();



结果是:

基本f
DDerived f 


可以预期,因为Base在其虚拟函数表中没有f(),而Derived应该具有f().

但是它是如何工作的呢?
Derived和DDerived应该从Base继承虚拟函数表,该表包含f1()而不是f().

但是Derived和DDerived在它们的虚拟函数表中也应该有f().他们有2个不同的虚拟表吗?
我使用Visual Studio 2008调试器,但只看到一个虚拟函数表,它不包含f().
虚拟函数f()在哪里?

谢谢!
Moti

解决方案

问题就在那里,调试器出了问题.

尝试打开内存窗口并找到p_derived->__vfptr,您将在vtable中看到所有条目.

Derived和DDerived应该具有两个不同的vtable,因为它们的第二个条目不同,即虚拟f.

vtable的布局取决于编译器,但似乎所有虚函数都使用VC ++进行了排序.

如果添加此帮助程序变量,则可以查看整个vtable:

void (**vt)() = *(void (***)())p_derived;



然后在监视窗口中检查vt,2.

[
现在,v-table哪里去了?好吧,如果您在一个翻译单元中全部声明了类和测试代码,则编译器可以优化所生成的代码以防止错误,只要它不会改变程序的可观察性即可.因此,只要代码能够正确生成两条消息,编译器就可以删除该v表,不需要它.

干杯,

Ash


以下内容将是不错的阅读方法:

http://www.openrce.org/articles/files/jangrayhood.pdf [ ^ ]


Hi
I''m running the following C++ code of polymorphism:

class Base
{
public:
    virtual void f1() {std::cout << "base f1" << std::endl;}
    void f() {std::cout << "base f" << std::endl;}
};

class Derived : public Base
{
public:
    virtual void f() {std::cout << "Derived f" << std::endl;}
};
class DDerived : public Derived
{
public:
    virtual void f() {std::cout << "DDerived f" << std::endl;}
};


Base* p_base = new DDerived();
p_base->f();
Derived* p_derived = new DDerived();
p_derived->f();



and the result is:

base f
DDerived f


it is expected since Base doesn''t have f() in its virtual function table, and Derived should have it.

But how does it work?
Derived and DDerived should inherit the virtual function table from Base, that contains f1() and not f().

But Derived and DDerived should also have f() in their virtual function table. Do they have 2 different virtual tables?
I use Visual Studio 2008 debugger and I see only one virtual function table and it doesn''t contain f().
Where is the virtual function f() located?

Thanks!
Moti

解决方案

It''s all there, it''s the debugger that is at fault.

Try opening a memory window and locate p_derived->__vfptr and you will see all entries in the vtable.

Derived and DDerived should have two different vtables, since their second entry differs, virtual f.

The layout of the vtable is compiler dependant, but it seems all virtual functions are put in order using VC++.

You can look at the entire vtable if you add this helper variable:

void (**vt)() = *(void (***)())p_derived;



and then inspect vt,2 in a watch window.

This[^] was a similar discussion, which should have all credit for the vt trick.


When you write:

p_base->f();



the compiler converts it to:

Base::f( p_base );



It doesn''t go anywhere near the v-table, it has no reason to - you told it f() wasn''t virtual for the base class.

When you write:

p_derived->f();



the compiler converts it to something like:

p_dervived->v_table[ 1 ]( p_derived );



as f() is marked as virtual in Derived. So the moral of this lot is you have to tell the compiler when you want virtual dispatch.

Now where has the v-table gone? Well if you''ve declared the classes and the test code all in one translation unit the compiler can optimise the generated code to buggery provided it doesn''t change the observable nature of the program. So provided the code generates the two messages correctly the compiler can remove the v-table, it doesn''t need it.

Cheers,

Ash


Following would be a good read:

http://www.openrce.org/articles/files/jangrayhood.pdf[^]


这篇关于派生类中的虚拟函数,但基类中的非虚拟函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆