【问题标题】:Pure virtual destructor vs. protected constructor + virtual dtor纯虚拟析构函数与受保护的构造函数 + 虚拟 dtor
【发布时间】:2016-01-22 19:25:00
【问题描述】:

当组织继承结构并需要使基类抽象时,有什么理由更喜欢纯虚析构函数而不是受保护的构造函数(反之亦然)?这个问题已经存在here,但接受的答案并没有真正回答它。问题

Base *ptr = new Derived();
delete ptr;

两种方法都可以解决:

  • 将 dtor 设为纯虚拟并为其定义主体
  • 使 dtor 虚拟化并使 ctor 受保护

据我了解,唯一不同的是在尝试Base *ptr = new Base() 时编译器错误:Cannot instantiate abstract class 在第一种情况下与Cannot access protected member 在第二种情况下,第一种情况更准确。这是风格的问题,还是有什么我不知道的?

作为一个有点相关的问题,相同的规则是否会应用于继承链中的某些类,这些类不是严格意义上的基类,但仍然应该是抽象的(即不能创建从 GameObject 继承的 Monster,但 @ 987654328@继承自Monster可以)?

【问题讨论】:

    标签: c++ inheritance abstract-class


    【解决方案1】:

    如果只有默认构造函数是protected,您仍然可以使用隐式定义的复制构造函数创建实例:

    struct ProtectedBase
    {
        virtual ~ProtectedBase() = default;
    protected:
        ProtectedBase(){}    
    };
    
    struct ProtectedDerived : ProtectedBase {};
    
    struct VirtualBase {
        virtual ~VirtualBase() = 0;
    };
    
    VirtualBase::~VirtualBase() = default;
    
    struct VirtualDerived : VirtualBase {};
    
    int main() {
        ProtectedBase a { ProtectedDerived{} }; //valid
        VirtualBase b { VirtualDerived{} };     //invalid
    }
    

    因此,您需要将所有构造函数显式标记为protected,包括任何隐式定义的构造函数。这似乎比简单地制作一个纯虚拟的析构函数并实现它更多的工作。错误地遗漏一些东西也容易得多。

    在更概念的层面上,如果您试图将类抽象化,则将其抽象化。只要你不盯着太久,实现一些使它看起来像抽象类的东西并不是很有帮助恕我直言。

    【讨论】:

    • At a more conceptual level, if you are trying to make a class abstract, then make it abstract. 好点 - 我想我的问题是理解“无法创建的基类”!=“抽象基类”。谢谢你再次提醒我隐式构造函数。
    【解决方案2】:

    如果您有一个带有受保护构造函数的非抽象类,您仍然可以在派生类的方法中实例化该类,因为它可以访问基类的受保护成员:

    // Devious code to bypass protection
    class Devious : public ProtectedBase {
    public:
        ProtectedBase *createBase() const {
            return new ProtectedBase();
        }
    }
    

    通过使类抽象化,您可以避免这种可能性。要使类抽象,您不需要将析构函数设为纯虚拟,只要至少一个成员函数是纯虚拟的即可。如果没有其他合理的成员函数可以使析构函数成为纯虚函数,则将析构函数设置为纯虚函数只是一个约定。

    在回答您的第二个问题时,基础是位于层次结构的顶部还是从其他基础继承并不重要。

    【讨论】:

      猜你喜欢
      • 2012-11-23
      • 2023-03-23
      • 2020-03-06
      • 2012-04-13
      • 2013-11-03
      • 2012-11-06
      • 2012-01-28
      • 2017-09-03
      • 2010-09-09
      相关资源
      最近更新 更多