C++ 如何知道何时函数必须是虚拟的?

C++ 如何知道何时函数必须是虚拟的?,c++,class,virtual-functions,C++,Class,Virtual Functions,在描述类时,如何知道函数何时必须是虚拟的 我知道虚函数是什么意思,但我就是不知道什么时候应该把它们虚化 谢谢您的类是否将具有虚拟函数取决于该类是否将用作基类,这应取决于设计和体系结构。如果您想调用函数,则函数应为虚拟函数。换句话说,虚拟函数表示可以在子类中自定义的行为。例如,考虑下面的类: class Car { public: const std::string & getId() const; virtual void startEngine() = 0; priva

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

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


谢谢

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

如果您想调用函数,则函数应为虚拟函数。换句话说,虚拟函数表示可以在子类中自定义的行为。例如,考虑下面的类:

class Car {
public:
    const std::string & getId() const;
    virtual void startEngine() = 0;
private:
    std::string id;
}
每辆车都有一个
Id
,这里不允许定制,因此没有必要将其虚拟化。子类不能修改该属性。然而,发动机的启动方式取决于具体的汽车,事实上不能在全球范围内定义。但我们知道,每辆车都必须先启动发动机,然后才能驾驶,所以我们将其定义为一个纯粹的虚拟功能


成语给出了一条重要的指导原则,说明何时将函数设为虚拟函数,何时不设为虚拟函数。

当您希望将您的类视为其他某个类的基类,并且您认为您的类中存在派生类可能重写的函数时,那么,很好地说明您应该将这些函数设置为虚拟的。使它们
虚拟
启用运行时多态性!这意味着,您可以多态地使用类,即使用基类类型的指针/引用,但指向派生类对象

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


请始终记住一件事:在设计多态类时,千万不要忘记将基类析构函数
设置为虚拟的

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

这取决于派生类是否可能对基类中的成员函数具有不同的功能。以多边形的设计为例类-

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;
    }
};

请注意,正方形和矩形是多边形的一种类型,但两者的面积计算不同。在这种设计情况下,如果成员函数可能在派生类中有不同的实现,则它在基类中需要是虚拟的。

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

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

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


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

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


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

如果您考虑类中的
virtual
关键字,请从该析构函数开始。@Kirill V.Lyadvinsky,不总是::)这篇文章没有对我的陈述做任何反驳。@VextoR-你为什么这么认为。如果操作数的静态类型与其动态类型不同,该怎么办<代码>多边形*obj=新正方形谢谢。在本例中,由于纯虚func,我们必须继承该类。但是,如果我们制作“void startEngine(){}”,它应该会起作用,对吗?
virtual void f() = 0;