虚拟继承中来自基础的虚拟调用

问题描述 投票:1回答:1

使用虚拟继承时进行虚拟呼叫时遇到问题。

下面是示例可编译代码,演示了在不使用虚拟继承的情况下可以工作的代码,以及在使用虚拟继承时在运行时将失败的代码。

基本类别这是这两种情况的基本指标:

#include <iostream>

class Base
{
public:
    Base() { }
    virtual ~Base() { }

    // we need to make this bad call a good one!
    virtual void bad_call(void* ptr)
    {
        Base* pThis = static_cast<Base*>(ptr);
        pThis->f();
    }

protected:
    virtual void f() { std::cout << x << std::endl; }
    int x = 0;
};

class Midle1 :
    virtual public Base
{
public:
    Midle1() { }
    ~Midle1() override { }
};

class Midle2 :
    virtual public Base
{
public:
    Midle2() { }
    ~Midle2() override { }
};

案例1良好在这种情况下,bad_callgood_call虚拟函数都可以使用,而没有使用虚拟继承(只是普通继承):

class GoodDerived :
    public Base
{
public:
    GoodDerived()
    {
    }
    ~GoodDerived() override
    {
    }
    void good_call(void* ptr)
    {
        GoodDerived* pThis = static_cast<GoodDerived*>(ptr);
        pThis->f();
    }

    void f() override
    {
        ++x;
        std::cout << x << std::endl;
    }
};

int main()
{
    GoodDerived good_derived;
    good_derived.good_call(&good_derived);  // OK, will print 1
    good_derived.bad_call(&good_derived);   // OK, will print 2

    std::cin.get();
    return 0;
}

案例2错误在这种情况下,将利用虚拟继承,good_call函数将成功,但bad_call将因“访问冲突读取位置”而失败。

class BadDerived :
    public Midle1,
    public Midle2
{
public:
    BadDerived() { }
    ~BadDerived() override { }
    void good_call(void* ptr)
    {
        BadDerived* pThis = static_cast<BadDerived*>(ptr);
        pThis->f();
    }

    void f() override
    {
        ++x;
        std::cout << x << std::endl;
    }
};

int main()
{
    BadDerived bad_derived;
    bad_derived.good_call(&bad_derived); // OK, will print 1
    bad_derived.bad_call(&bad_derived); // ERROR: causes access violation

    std::cin.get();
    return 0;
}

问题第二种情况是一个简单的代码,演示了我现在在项目中遇到的问题,我需要有关如何解决此问题的帮助,为什么虚拟继承会引起麻烦?

为什么第一种情况效果很好,而第二种效果不好?我正在使用msvc编译器顺便说一句。

c++ inheritance virtual
1个回答
0
投票

拨打电话:

bad_derived.bad_call(static_cast<Base*>(&bad_derived));

您想指向对象的基础部分,但是使用虚拟继承时,不能保证将对象放置在何处。

© www.soinside.com 2019 - 2024. All rights reserved.