【问题标题】:How do you call a virtual method stored in the base class and called by a class that inherits that base class twice?如何调用存储在基类中并由继承该基类两次的类调用的虚拟方法?
【发布时间】:2019-07-30 12:04:28
【问题描述】:

这段代码演示了这个问题:

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 方法中,应该调用覆盖Subclass1_print 方法,但是Subclass1::print(); 语句会再次调用当前方法。如果注释掉 virtual void _print() = 0; 语句,则可以避免此问题。
为什么使用虚拟 _print 方法会阻止我调用重载的虚拟方法 Subclass1::_print 以及有什么解决方案让我不必不用虚拟方法?

【问题讨论】:

    标签: c++ class oop multiple-inheritance


    【解决方案1】:
    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";
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 2021-10-30
      • 2023-04-01
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多