【问题标题】:How to know when function has to be virtual?如何知道函数何时必须是虚拟的?
【发布时间】:2011-07-14 21:11:49
【问题描述】:

在描述一个类时,如何知道函数何时必须是虚拟的?

我知道虚函数是什么意思,但我就是不知道什么时候应该把它们变成虚函数

谢谢

【问题讨论】:

标签: c++ class virtual-functions


【解决方案1】:

如果您想通过指针或对基类的引用来使用您的对象,您需要将函数设为虚拟。然后,您可以调用派生类的函数,而无需确切知道它是什么类型。

如果你单独使用每个类,并且知道每个对象的类型,那么即使你使用派生类也不需要虚函数。

【讨论】:

    【解决方案2】:

    这取决于派生类是否有可能对基类中存在的成员函数具有不同的功能。采用Polygon类的设计-

    class Polygon
    {
        public:
        virtual float area();
        virtual ~Polygon(){};  // Since Polygon is a polymorphic class, it destructor needs to be virtual.
    };
    

    成员函数Polygon::area() 需要是虚拟的。为什么 ?因为所有多边形的面积计算不一样。

    class Rectangle : public Polygon
    {
        public:
        float area()
        {
             // area = 2* (length+breadth) ;
        }
    };
    

    同样——

    class Square : public Polygon
    {
        public:
        float area()
        {
             // area = side*side;
        }
    };
    

    请注意,Square、Rectangle 是 Polygon 的一种,但两者的面积计算方式不同。在这种设计情况下,成员函数可能在派生类中不同的实现,它需要在基类中

    【讨论】:

    • @VextoR - 你为什么这么认为。如果操作数的静态类型与动态类型不同怎么办? Polygon *obj = new Square;
    【解决方案3】:

    如果你想调用它们,函数应该是虚拟的polymorphically。换句话说,虚函数表达了可以在子类中定制的行为。例如,考虑以下类:

    class Car {
    public:
        const std::string & getId() const;
        virtual void startEngine() = 0;
    private:
        std::string id;
    }
    

    每辆车都有一个Id,这里不允许自定义,因此将其设为虚拟是没有意义的。子类不应修改该属性。然而,发动机的启动方式取决于具体的汽车,实际上不能全局定义。但我们确实知道,每辆汽车都必须启动引擎才能开车,因此我们将其定义为纯虚函数。

    Non-Virtual Interface 成语给出了何时将函数设为虚拟函数以及何时不设为虚拟函数的重要指南。

    【讨论】:

    • 谢谢。在这个例子中,由于纯虚函数,我们必须继承类。但如果我们制作“void startEngine() {};”无论如何它应该可以工作,对吧?
    【解决方案4】:

    当您知道该方法的行为可能或将要在从该类继承的类中发生变化时,您应该使该方法成为虚拟方法。更准确地说,如果您希望子类覆盖该方法,则将其设为虚拟。如果您不想在基类中实现该方法,请将其设为纯虚拟: 即:

    virtual void f() = 0;
    

    这样你的基类就不能被实例化(你可能不希望它被实例化,因为它仍然有未实现的方法)。

    使用虚拟方法可以让类多态为您工作。

    如果您知道某个方法不会改变行为,那么就不要将其设为虚拟(查找虚拟函数调用比“最终”/非虚拟函数调用需要更长的时间)。

    【讨论】:

      【解决方案5】:

      如果您希望您的类被视为其他类的基类,并且您认为您的类中有一些函数可能会被派生类覆盖,那么很好地表明您应该使用这些函数virtual .使它们virtual 启用运行时多态性!这意味着,您可以多态地使用类,即使用类型基类的指针/引用,但指向派生类对象!

      简而言之,在基于接口的类设计中,应该使函数virtual

      永远记住一件事:在设计多态类的时候一定不要忘记让基类析构函数virtual

      【讨论】:

        【解决方案6】:

        在软件设计方面,如果您尝试定义抽象类或接口,您将使用 virtual 关键字来强制执行动态多态性。

        【讨论】:

          【解决方案7】:

          您的类是否具有虚函数取决于该类是否将用作基类,而这应取决于设计和架构。

          【讨论】:

            猜你喜欢
            • 2013-03-09
            • 1970-01-01
            • 2015-12-31
            • 2021-10-05
            • 2012-01-19
            • 1970-01-01
            • 2019-08-16
            • 2013-11-17
            • 1970-01-01
            相关资源
            最近更新 更多