如何调用存储在基类中并由继承该基类两次的类调用的虚拟方法?

时间:2019-03-08 12:44:03

标签: c++ class oop multiple-inheritance

此代码演示了问题:

class Base
{
public:
    explicit Base(std::function<void()> const& printFunc) :
        _printFunc(printFunc)
    {
    }

    void print()
    {
        _printFunc();
    }
private:
   std::function<void()> _printFunc{};
private:
    virtual void _print() = 0; // If this line is commented out, then 
                               // `Subclass1::_print()` can be called.
};

class Subclass1 : public Base
{
public:
    explicit Subclass1() :
        Base([this]() { _print(); })
    {
    }
private:
    void _print() /*override*/
    {
        std::cout << "Subclass1\n";
    }
};

class Subclass2 : public Base, public Subclass1
{
public:
    using fromLowestSubclass = Base;
public:
    explicit Subclass2() :
        Base([this]() { _print(); }), Subclass1()
    {
    }
private:
    void _print() /*override*/
    {
        // Here is the problem:
        Subclass1::print(); // or: static_cast<Subclass1*>(this)->print(); 

        std::cout << "Subclass2\n";
    }
};

int main()
{
    Subclass2 sc2{};
    sc2.fromLowestSubclass::print();

    return 0;
}

Subclass2::_print方法中,应调用_print的重写Subclass1方法,但是Subclass1::print();语句将再次调用当前方法。如果将语句virtual void _print() = 0;注释掉,则可以避免此问题。
为什么使用虚拟_print方法会阻止我调用重载的虚拟方法Subclass1::_print,并且有什么解决方案,这样我就不必没有虚拟方法了?

1 个答案:

答案 0 :(得分:0)

class Base
{
    ....
private:
    virtual void _print() = 0; 
}

这意味着:您可以覆盖_print,但不能调用它,只有Base有权调用它。

现在:

class Base
{
public:
    void print()
    {
        _printFunc();
    }

这样做,它将_printFunc作为虚函数调用,该虚函数与当前对象实例化匹配。它不计量print()的调用方式。

添加Subclass1::作为前缀只会更改名称范围,并且不会影响方法的行为。它只影响名称范围。

现在,如果虚拟方法具有这样的前缀,那么选择名称范围将指示编译器放弃抽象,而需要调用特定方法。在这种情况下,调用方法时不会引用虚拟表。

双重继承对此问题没有影响。

您可以提供一个可以从祖先处调用的辅助方法:

class Subclass1 : public Base
{
    ....
protected:
    void sub1_print() // not virtual
    {
        std::cout << "Subclass1\n";
    }
private:
    void _print() /*override*/
    {
        sub1_print();
    }
};

class Subclass2 : public Base, public Subclass1
{
    ....
private:
    void _print() /*override*/
    {
        sub1_print();

        std::cout << "Subclass2\n";
    }
};