【问题标题】:Is it dangerous to create pure virtual function of a virtual function?创建虚函数的纯虚函数是否危险?
【发布时间】:2017-03-31 14:55:38
【问题描述】:

假设我们有一个抽象类NonEditableSuperBase,我们从中创建另一个抽象类MyBase

第一个类NonEditableSuperBase有一个虚函数(非纯虚函数)。但是,我想强制如果有人创建一个派生自 MyBase 的类,他/她必须提供上述函数的实现。

因此,我的想法是在MyBase 中将函数定义为纯虚函数。

我的问题:这是一个坏主意,因为它在 NonEditableSuperBase 中只是虚拟的?

示例:

//NonEditableSuperBase.h
class NonEditableSuperBase
{
  ...
  public:
    virtual int someMethod(); //It has an implementation, suppose {return 42;}
};

//MyBase.h
class MyBase: public NonEditableSuperBase
{
  public:
     explicit MyBase();       
     virtual ~MyBase() = default;       
     virtual int someMethod() = 0;  //I make it pure virtual
};

//MyBase.cpp
MyBase::MyBase() : NonEditableSuperBase() { }

//Now someone creates a derived class from MyBase.
class SuperDerived : public MyBase
{
  public:
    explicit SuperDerived();
    int someMethod(); //The user must create an implementation of the function
};

更新: 例如,在我的例子中,我想从 Qt 框架的 QAbstractTableModel 类创建一些派生类。为了重用一些代码,我想创建一个中间抽象类。

QAbstractTableModel <- MyAbstractModel <- MyModelA (or MyModelB ... etc).

但是,我想确保模型(MyModelA、MyModelB)重新实现 QAbstractTableModel 的一些虚函数(如 ::index() 函数),因为 MyAbstractModel 的一些附加方法需要特定实现引物功能。

【问题讨论】:

  • 这是一个足够公平的问题,但对于不处理编程风格问题的 StackOverflow 来说不是。如果你定义了一个基方法,你必须想知道发生了什么使它在中间类中无效。
  • 完全有可能实现你想要的。没有什么危险的。它是否是一种好的风格是非常主观的。
  • gcc 4.9 会在 SuperDerived 的实例化时发出错误信号(假设 Derived 是 MyBase)如果 someMethod 被注释掉/未在 SuperDerived 中定义,正如@JesperJuhl 解释的那样
  • 您是否打算让 MyBase 使用来自 NonEditableSuperBase 的私有继承?
  • 我会在 NonEditableSuperBase 中进行虚拟保护

标签: c++ abstract-class pure-virtual


【解决方案1】:

来自ISO IEC 14882 2014

§ 10.4 说:

5 [注意:抽象类可以派生自非抽象类,纯虚函数可以 覆盖一个不纯的虚函数。 ——尾注]

所以这是完全可以做到的。

用例示例:

您可以拥有一个基本类型,即作为具体类型(基类)实现。现在,对于子类型,我们可能需要更多的附加信息。所以,我们可以有一个抽象的中间对象来满足我们的需求。

【讨论】:

    【解决方案2】:

    [我假设 MyBase 的意图是公开从 NonEditableSuperBase 派生,这不是问题中的代码示例实际执行的操作。]

    这似乎并不危险,但考虑到像 SuperDerived 这样从 MyBase 派生的类可以明确选择使用 NonEditableSuperBase 实现。

    class SuperDerived : public MyBase {
      public:
        using NonEditableSuperBase::someMethod;
        // Or, explicitly:
        // int someMethod() override { return NonEditableSuperBase::someMethod(); }
    };
    

    这满足了 MyBase 提出的纯虚拟要求,但就像 MyBase 没有该要求一样。你已经让 SuperDerived 的作者做了一些事情,但你实际上并没有阻止他们使用最终基类的实现。

    【讨论】:

    • 首先,是的,我想公开从 NonEditableSuperBase 派生,我已经更正了代码,谢谢。其次,我并不打算阻止用户使用 NonEditableSuperBase 方法,只是提醒他们必须实现它们(如果他们做了你已经证明他们知道自己在做什么)
    • 查看另一个关于在基类中有实现的纯虚拟方法的问题。这达到了相同的效果:提供合理的默认行为,同时要求派生类的实现者有意识地选择获得默认行为。 stackoverflow.com/questions/2089083/…
    猜你喜欢
    • 2013-01-18
    • 2022-01-13
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2012-01-28
    • 1970-01-01
    • 2012-08-27
    相关资源
    最近更新 更多