【问题标题】:How can I override a purely virtual method, yet still force child classes to implement the same method?如何覆盖纯虚拟方法,但仍强制子类实现相同的方法?
【发布时间】:2021-07-01 10:40:03
【问题描述】:

我有一个带有一个纯虚方法的抽象基类:

class Base
{
public:
    virtual void update() = 0;
};

有什么方法可以创建一个继承自Base 的类,覆盖update 方法,但仍强制其子级实现update 方法?像这样:

class Base2 : public Base
{
public:
    void update() override
    {
        if(bSomeCondition)
        {
            update(); //Calls child's update method
        }
    }
    virtual void update() = 0; // Obviously not like this
};

我知道我可以在 Base2 中创建两个名称稍有不同的新纯虚拟方法,然后在子类中覆盖它们,但如果可能的话,我真的很想保留这些方法名称。

我猜这是不可能的?

【问题讨论】:

  • 所以,这是可能的,但目前还不清楚你希望实现什么。什么时候调用中间函数,为什么?
  • 我怀疑你最好创建一个 Base0,Base 和 Base2 都是覆盖 Base0 功能的子类
  • 通常的方法是直接从Base 派生类,而不是从Base2。换句话说,不要从具体(可实例化)类派生。 C++11 及更高版本,可以通过将 Base2 标记为 final 来强制执行。
  • "// Obviously not like this" -- 好吧,显然“显然”的那一行是显而易见的方法。显然是“明显”行上方的内联定义是问题所在。 :) 我最近有没有提到“显然”比真实的陈述更经常限定虚假陈述?每当你发现自己说的很明显时,都要怀疑自己!

标签: c++


【解决方案1】:

可以为纯虚函数提供定义,而不是内联。

class Base2 : public Base
{
public:
    void update() override = 0;
};

void Base2::update() // Base2 is abstract regardless of this
{
    if(bSomeCondition)
    {
        update(); 
    }
}

但是,这对于Base2::update 的当前实现没有用处。因为无论如何子类都必须覆盖它,所以除非明确使用,否则不会调用Base2 版本:

class Child: public Base2
{
public:
    void update() override
    {
        Base2::update(); //infinite recursion with such implementation
    }
};

// the other way would be to require calling it explicitly at call site

std::unique_ptr<Base2> ptr = std::make_unique<Child>();
ptr->Base2::update(); 

你应该做的是提供一个实现和另一个要调用的纯虚函数(可能是protected):

class Base2 : public Base
{
public:
    void update() override;

protected:
    virtual void doStuff() = 0;
};

void Base2::update()
{
    if(bSomeCondition)
    {
        doStuff(); //Calls child's update method
    }
}

【讨论】:

  • 调用Base2::update()(而不是update())的子类不会导致任何递归。
  • @StoryTeller-UnslanderMonica 会不会是这样:Child::update() 调用 Base2::update(),而后者又调用不​​合格的 update(),它被解析为 Child::update(),它再次调用 Base2::update() ?我想我应该用代码来说明为什么这可能是个坏主意。
  • 只是因为您选择在中间纯虚函数中进行不合格的调用。不过,这不是该机制所固有的——您可能只是记录了“不要调用这个”。诚然,我想不出一个 use 除非你试图避免在销毁期间进行虚函数调用时崩溃。
  • 啊,OP的例子是绝望的尝试。是的,那将是无限的。但这在您的答案中看起来像是一个更普遍的问题。不同的功能确实是前进的道路。
【解决方案2】:

不,这是不可能的,在我看来这将非常难以辨认。

【讨论】:

  • “不可能” - 显然是错误的。
猜你喜欢
  • 2018-06-02
  • 2012-03-17
  • 2011-05-21
  • 2012-07-20
  • 1970-01-01
  • 2014-08-21
  • 2018-08-01
  • 1970-01-01
  • 2017-11-18
相关资源
最近更新 更多