【问题标题】:Is there a way to "delete" a pure virtual function?有没有办法“删除”纯虚函数?
【发布时间】:2009-06-08 20:14:14
【问题描述】:

我有一个带有几个纯虚函数的抽象类,而我从中派生的一个类不使用其中一个纯虚函数:

class derivative: public base
{
public:
    int somevariable;
    void somefunction();
};

无论如何,当我尝试编译它时,我得到一个错误(显然,如果从抽象类派生并且不覆盖所有纯虚函数,则类仍然被认为是抽象的)。无论如何,定义一个函数似乎毫无意义

int purevirtfunc(){return 0;}

只是因为它需要通过技术来定义。无论如何从抽象类派生一个类而不使用抽象类的纯虚函数之一?

【问题讨论】:

  • 如果有办法,如果代码调用其中一个未实现的方法,您会期望发生什么?

标签: c++ inheritance


【解决方案1】:

如果您的派生类不“使用”基类纯虚函数,那么派生类不应该从基类派生,或者 PVF 不应该存在。无论哪种情况,您的设计都有问题,需要重新考虑。

不,没有办法删除 PVF。

【讨论】:

    【解决方案2】:

    纯虚拟类是一个接口,您的代码将期望实现该接口。如果您实现了该接口但没有实现其中一种方法,会发生什么?调用你的接口的代码怎么知道你没有实现这个方法?

    您的选择是:

    1. 按照您的描述实现方法(将其设为私有表示不应使用它)。
    2. 更改您的类层次结构以考虑设计更改。

    【讨论】:

      【解决方案3】:

      从抽象类派生的目的是外部代码可以使用抽象类并期望所有功能都已正确实现。能够取消实现一个方法会破坏这个目的,使代码无法编译。但是,如果您愿意,您可以随意抛出异常。

      【讨论】:

        【解决方案4】:

        这根本不是技术问题。如果您的派生类没有表现出父类的所有行为,则不应从父类派生。这是一种主要的设计气味,您可能需要进行一些设计重构。

        【讨论】:

          【解决方案5】:

          当您从具有纯虚函数的类继承时,您必须实现这些函数。如果你不这样做,那么你的派生类也是抽象的,你不能创建派生类的对象。

          【讨论】:

          • 如果你经常从这个接口继承,你也可以创建一个你继承的空实现来做存根。
          【解决方案6】:

          没有。按照您的建议,在基类中提供默认实现或在派生类中提供简单实现。

          【讨论】:

            【解决方案7】:

            已经有了很好的答案,但如果您想从理论 OO 设计方面获得更多信息,请查看Liskov substitution principle

            【讨论】:

              【解决方案8】:

              允许这样做没有任何意义。如果你在没有实现的情况下调用函数会发生什么?运行时错误(那会很愚蠢)?您可能会争辩说在某些情况下它可能是编译时错误,但如果确切类型未知(例如,您将指向派生类实例的指针传递给函数),则这是不可能的。

              【讨论】:

                【解决方案9】:

                正如许多人已经说过的,听起来基方法不应该是纯虚拟的,或者您应该重新考虑派生类是否真的是 ISA 基方法。

                但是,可以在基类中提供纯虚方法的实现。这可以作为派生类的默认实现,但您仍然需要派生类明确选择基类的实现。

                我不知道这是否能帮助您解决问题。

                【讨论】:

                  【解决方案10】:

                  不,没有。当这种情况发生时,后期绑定语言中的约定(这可能是合理的,但请考虑您的设计以查看此方法是否可以移动到其他地方,也许可以移动到它的抽象类),是引发异常,并确保该方法的用户方法知道某些实现可能会引发该异常。

                  【讨论】:

                    【解决方案11】:

                    当我试图在派生类中隐藏方法 getVertex() 时,我似乎遇到了同样的问题。 也许有帮助。

                        class Body2D
                    {
                    public:
                        virtual ~Body2D() = default;
                    
                        virtual double getCenter() const = 0;
                        virtual double getVertex() const = 0;
                    };
                    
                    class Ellipse : public Body2D
                    {
                    public:
                        Ellipse(){};
                        double getCenter() const override{};
                    private:
                        double getVertex() const override{};
                    };
                    

                    【讨论】:

                    • 这并不能真正回答问题。如果您有其他问题,可以点击 提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review
                    【解决方案12】:

                    你就不能这样做

                    class Foo {
                    public:
                        virtual void foo() = 0;
                    };
                    
                    class Bar {
                    public:
                        virtual void foo() = delete;
                    };
                    

                    【讨论】:

                    • 这根本不能回答问题。此处显示的代码中甚至没有任何继承。
                    猜你喜欢
                    • 2014-10-29
                    • 1970-01-01
                    • 2015-02-15
                    • 2010-10-01
                    • 2017-05-22
                    • 2013-01-15
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多