C ++:莫名其妙的"纯虚函数调用"错误

时间:2016-08-01 16:49:28

标签: c++ c++11 base-class pure-virtual visual-studio-2015

我在使用Microsoft Visual C ++ 2015时遇到了一些困难,并且能够通过一个小程序复制该问题。鉴于以下类别:

class BaseClass {
public:
    BaseClass()
        : mValue( 0 )
        , mDirty( true )
    {}
    virtual ~BaseClass() {}
    virtual int getValue() const { if( mDirty ) updateValue(); return mValue; }

protected:
    virtual void updateValue() const = 0;

    mutable bool mDirty;
    mutable int  mValue;
};

class DerivedClass : public BaseClass {
public:
    DerivedClass() {}

protected:
    void updateValue() const override
    {
        mValue++;
        mDirty = false;
    }
};

class Impersonator {
public:
    Impersonator() {}

    // conversion operator
    operator DerivedClass() const
    {
        return DerivedClass();
    }

    // conversion method
    DerivedClass toDerived() const
    {
        return DerivedClass();
    }
};

我得到一个纯粹的虚拟函数调用"我执行以下操作时出错:

void use( const BaseClass &inst )
{
    // calls `getValue` which in turns calls the virtual function 'updateValue'
    int value = inst.getValue();
}

int main()
{
    // creates a temporary, then passes it by reference:
    use( DerivedClass() ); // this works

    // calls conversion operator to create object on stack, then passes it by reference:
    DerivedClass i = Impersonator();
    use( i ); // this works

    // calls conversion method to create a temporary, then passes it by reference:
    use( Impersonator().toDerived() ); // this works

    // calls conversion operator to create a temporary, then passes it by reference:
    Impersonator j = Impersonator();
    use( j ); // causes a pure virtual function call error!

    return 0;
}

鉴于我无法更改void use(const BaseClass&)函数,我是否可以更改Impersonator类中的任何内容以允许使用上次调用而不会产生调试错误?

2 个答案:

答案 0 :(得分:2)

缓解我看到的问题的唯一方法是向operator const BaseClass&()添加Impersonator并让它返回对DerivedClass的引用。

这将创建比编译器尝试使用的有问题/错误的转换更好的转换。

当然Impersonator将无法按值返回并创建一个临时对象,因此它必须拥有一个DerivedClass对象或许多对象,并在适当的时候以某种方式处理它们。适用于此演示程序的最简单方法是让它返回对其数据成员的引用,但真正的程序可能必须执行其他操作。

class Impersonator {
public:
    Impersonator() {}

    // conversion operator
    operator DerivedClass()
    {
        return d;
    }
    operator const BaseClass&()
    {
        return d;
    }

private:
    DerivedClass d;
};

答案 1 :(得分:1)

这是一种解决方法。为use创建一个包含const DerivedClass&

的包装器
//I get a "pure virtual function call" error when I do the following :
void use(const BaseClass &inst)
{
    // calls `getValue` which in turns calls the virtual function 'updateValue'
    int value = inst.getValue();
}

void use(const DerivedClass &inst) {
    use(static_cast<const BaseClass&>(inst));
}

更好的匹配意味着将选择变通方法包装器,因此将创建一个正确类型的临时表,并将对该表达式的引用传递给真正的use实现。