【问题标题】:void* convert to base class and invoke virtual function [duplicate]void *转换为基类并调用虚函数[重复]
【发布时间】:2014-03-04 02:42:37
【问题描述】:

我有一些这样的代码:

#include <iostream>

using namespace std;
//base class
class Base
{
    public:
        Base(){}

        virtual void f()
        {
            cout<<"father.f()"<<endl;
        }
        virtual ~Base(){}
};
//a empty class
class Base1
{
    public:
        Base1(){}
        virtual ~Base1()
        {
            cout<<"~base1"<<endl;
        }
};
//the child class of the base class
class Child :public Base
{
    public:
        Child(){}
        virtual ~Child(){}
};
//the grandchild class of the base class,and child class of the base1 class
class Grand :public Base1,public Child
{
    public:
        Grand(){}
        virtual ~Grand(){}
        //overwrite base's f()
        void f()
        {
            cout<<"grand.f"<<endl;
        }
};
int main()
{
    void *v = new Grand();
    Base *b = (Base*)(v);
    //i think it print "father.f()",but it print"~base1"
    b->f();
    return 0;
}

我在 code::blocks(version13.12) 中运行这些代码,但它打印“~base1”,我不知道为什么它不打印“father.f()”。我认为 v 点到grand虚拟表的地址,所以当我将v转换为base并调用f函数时,然后b调用虚拟表中的第一个虚拟函数。

我不知道我是对还是错,你能告诉我吗。谢谢大家!

【问题讨论】:

    标签: c++ void-pointers


    【解决方案1】:

    因为使用多重继承,您不能在不通过子类的情况下直接转换到上层类。这是因为 void* 不包含任何有关构成最终 Grand* 实例的各种类的内存布局信息。

    要解决此问题,您确实需要将其转换为它的运行时类型:

    Base *b = (Base*)(Grand*)v;
    b->f();
    

    考虑一下布局可以在不同的位置有Base。想想另一个

    class Grand2 : public Something, public Else, public Base1, public Child {
      ..
    }
    

    现在,Base 位于 Grand2 结构内的什么位置?与Grand 相比处于不同的位置。编译器如何知道从指向非指定类(可能是GrandGrand2)的指针开始的正确偏移量?

    【讨论】:

    • 或者,类似地,先转换为Base*,然后再转换为void*
    • 谢谢,但我不明白为什么 b-f() 会调用 ~base1()。你能告诉我为什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 2013-04-07
    • 2010-09-28
    • 2016-11-20
    • 1970-01-01
    • 2018-10-21
    相关资源
    最近更新 更多