我应该在基类中声明所有虚函数吗?

时间:2022-09-20 10:39:13

When I declare a base class, should I declare all the functions in it as virtual, or should I have a set of virtual functions and a set of non-virtual functions which I am sure are not going to be inherited?

当我声明一个基类时,我应该将其中的所有函数声明为虚拟,还是应该有一组虚函数和一组非虚函数,我相信这些函数不会被继承?

8 个解决方案

#1


A function only needs to be virtual iff a derived class will implement that function in a different way.

如果派生类将以不同的方式实现该函数,则函数只需要是虚拟的。

For example:

class Base {
public:
  void setI (int i)  // No need for it to be virtual
  {
    m_i = i;
  }

  virtual ~Base () {}         // Almost always a good idea

  virtual bool isDerived1 ()  // Is overridden - so make it virtual
  {
    return false;
  }

private:
  int m_i;
};

class Derived1 : public Base {
public:
  virtual ~Derived () {}

  virtual bool isDerived1 ()  // Is overridden - so make it virtual
  {
    return true;
  }
};

As a result, I would error the side of not having anything virtual unless you know in advance that you intend to override it or until you discover that you require the behaviour. The only exception to this is the destructor, for which its almost always the case that you want it to be virtual in a base class.

因此,除非您事先知道您打算覆盖它或直到您发现需要该行为,否则我会错误地认为没有任何虚拟内容。唯一的例外是析构函数,对于它来说,它几乎总是希望它在基类中是虚拟的。

#2


You should only make functions you intend and design to be overridden virtual. Making a method virtual is not free in terms of both maintenance and performance (maintenance being the much bigger issue IMHO).

您应该只创建您想要的功能并设计为覆盖虚拟。在维护和性能方面,使虚拟方法不是免费的(维护是更大的问题恕我直言)。

Once a method is virtual it becomes harder to reason about any code which uses this method. Because instead of considering what one method call would do, you must consider what N method calls would do in that scenario. N represents the number of sub classes which override that method.

一旦方法是虚拟的,就很难推断使用这种方法的任何代码。因为不是考虑一个方法调用会做什么,而是必须考虑N方法调用在该场景中会做什么。 N表示覆盖该方法的子类的数量。

The one exception to this rule is destructors. They should be virtual in any class which is intended to be derived from. It's the only way to guarantee that the proper destructor is called during deallocation.

这个规则的一个例外是析构函数。它们应该在任何旨在派生的类中是虚拟的。这是保证在释放期间调用正确的析构函数的唯一方法。

#3


The non-virtual interface idiom (C++ Coding Standards item 39) says that a base class should have non-virtual interface methods, allowing the base class to guarantee invariants, and non-public virtual methods for customization of the base class behaviour by derived classes. The non-virtual interface methods call the virtual methods to provide the overridable behaviour.

非虚拟接口习惯用法(C ++ Coding Standards第39项)表示基类应该具有非虚拟接口方法,允许基类保证不变量,以及非公共虚拟方法,用于通过派生类定制基类行为。非虚拟接口方法调用虚方法以提供可覆盖的行为。

#4


I tend to make only the things I want to be overridable virtual. If my initial assumptions about what I will want to override turn out to be wrong, I go back and change the base class.

我倾向于只制作我想要覆盖虚拟的东西。如果我对我想要覆盖的内容的初步假设结果是错误的,我会回去更改基类。

Oh, and obviously always make your destructor virtual if you're working on something that will be inherited from.

哦,显然总是让你的析构函数虚拟,如果你正在处理将继承的东西。

#5


If you are creating a base class ( you are sure that somebody derives the class ) then you can do following things:

如果您正在创建基类(您确定有人派生了该类),那么您可以执行以下操作:

  • Make destructor virtual (a must for base class)
  • 使析构函数成为虚拟(基类的必备)

  • Define methods which should be derived and make them virtual.
  • 定义应该派生的方法并使它们成为虚拟的。

  • Define methods which need not be ( or should not be) derived as non-virtual.
  • 定义不需要(或不应该)派生为非虚拟的方法。

  • If the functions are only for derived class and not for base class then mark them as protected.
  • 如果函数仅用于派生类而不用于基类,则将它们标记为受保护。

#6


Compiler wouldn't know which actual piece of code will be run when pointer of base type calls a virtual function. so the actual piece of code that would be run needs to be evaluated at run-time according to which object is pointed by base class pointer. So avoid the use of virtual function if the function is not gonne be overriden in an inherited class.

当基类型的指针调用虚函数时,编译器不知道将运行哪一段实际代码。因此,需要在运行时根据基类指针指向哪个对象来评估要运行的实际代码片段。因此,如果函数不是在继承的类中重写,则避免使用虚函数。

TLDR version: "you should have a set of virtual functions and a set of non-virtual functions which you are sure are not going to be inherited." Because virtual functions causes a performance decrease at run-time.

TLDR版本:“你应该拥有一组虚拟函数和一组非虚函数,你肯定不会继承这些函数。”因为虚函数会导致运行时性能下降。

#7


The interface functions should be, in general, virtual. Functions that provide fixed functionality should not.

接口函数通常应该是虚拟的。提供固定功能的功能不应该。

#8


Why declare something virtual until you are really overriding it? I believe it's not a question of being sure or not. Follow the facts: is it overriden somewhere? No? Then it must not be virtual.

为什么要声明一些虚拟的东西,直到你真的重写它为止?我相信这不是一个肯定与否的问题。遵循事实:它是否覆盖某处?没有?那它一定不是虚拟的。

#1


A function only needs to be virtual iff a derived class will implement that function in a different way.

如果派生类将以不同的方式实现该函数,则函数只需要是虚拟的。

For example:

class Base {
public:
  void setI (int i)  // No need for it to be virtual
  {
    m_i = i;
  }

  virtual ~Base () {}         // Almost always a good idea

  virtual bool isDerived1 ()  // Is overridden - so make it virtual
  {
    return false;
  }

private:
  int m_i;
};

class Derived1 : public Base {
public:
  virtual ~Derived () {}

  virtual bool isDerived1 ()  // Is overridden - so make it virtual
  {
    return true;
  }
};

As a result, I would error the side of not having anything virtual unless you know in advance that you intend to override it or until you discover that you require the behaviour. The only exception to this is the destructor, for which its almost always the case that you want it to be virtual in a base class.

因此,除非您事先知道您打算覆盖它或直到您发现需要该行为,否则我会错误地认为没有任何虚拟内容。唯一的例外是析构函数,对于它来说,它几乎总是希望它在基类中是虚拟的。

#2


You should only make functions you intend and design to be overridden virtual. Making a method virtual is not free in terms of both maintenance and performance (maintenance being the much bigger issue IMHO).

您应该只创建您想要的功能并设计为覆盖虚拟。在维护和性能方面,使虚拟方法不是免费的(维护是更大的问题恕我直言)。

Once a method is virtual it becomes harder to reason about any code which uses this method. Because instead of considering what one method call would do, you must consider what N method calls would do in that scenario. N represents the number of sub classes which override that method.

一旦方法是虚拟的,就很难推断使用这种方法的任何代码。因为不是考虑一个方法调用会做什么,而是必须考虑N方法调用在该场景中会做什么。 N表示覆盖该方法的子类的数量。

The one exception to this rule is destructors. They should be virtual in any class which is intended to be derived from. It's the only way to guarantee that the proper destructor is called during deallocation.

这个规则的一个例外是析构函数。它们应该在任何旨在派生的类中是虚拟的。这是保证在释放期间调用正确的析构函数的唯一方法。

#3


The non-virtual interface idiom (C++ Coding Standards item 39) says that a base class should have non-virtual interface methods, allowing the base class to guarantee invariants, and non-public virtual methods for customization of the base class behaviour by derived classes. The non-virtual interface methods call the virtual methods to provide the overridable behaviour.

非虚拟接口习惯用法(C ++ Coding Standards第39项)表示基类应该具有非虚拟接口方法,允许基类保证不变量,以及非公共虚拟方法,用于通过派生类定制基类行为。非虚拟接口方法调用虚方法以提供可覆盖的行为。

#4


I tend to make only the things I want to be overridable virtual. If my initial assumptions about what I will want to override turn out to be wrong, I go back and change the base class.

我倾向于只制作我想要覆盖虚拟的东西。如果我对我想要覆盖的内容的初步假设结果是错误的,我会回去更改基类。

Oh, and obviously always make your destructor virtual if you're working on something that will be inherited from.

哦,显然总是让你的析构函数虚拟,如果你正在处理将继承的东西。

#5


If you are creating a base class ( you are sure that somebody derives the class ) then you can do following things:

如果您正在创建基类(您确定有人派生了该类),那么您可以执行以下操作:

  • Make destructor virtual (a must for base class)
  • 使析构函数成为虚拟(基类的必备)

  • Define methods which should be derived and make them virtual.
  • 定义应该派生的方法并使它们成为虚拟的。

  • Define methods which need not be ( or should not be) derived as non-virtual.
  • 定义不需要(或不应该)派生为非虚拟的方法。

  • If the functions are only for derived class and not for base class then mark them as protected.
  • 如果函数仅用于派生类而不用于基类,则将它们标记为受保护。

#6


Compiler wouldn't know which actual piece of code will be run when pointer of base type calls a virtual function. so the actual piece of code that would be run needs to be evaluated at run-time according to which object is pointed by base class pointer. So avoid the use of virtual function if the function is not gonne be overriden in an inherited class.

当基类型的指针调用虚函数时,编译器不知道将运行哪一段实际代码。因此,需要在运行时根据基类指针指向哪个对象来评估要运行的实际代码片段。因此,如果函数不是在继承的类中重写,则避免使用虚函数。

TLDR version: "you should have a set of virtual functions and a set of non-virtual functions which you are sure are not going to be inherited." Because virtual functions causes a performance decrease at run-time.

TLDR版本:“你应该拥有一组虚拟函数和一组非虚函数,你肯定不会继承这些函数。”因为虚函数会导致运行时性能下降。

#7


The interface functions should be, in general, virtual. Functions that provide fixed functionality should not.

接口函数通常应该是虚拟的。提供固定功能的功能不应该。

#8


Why declare something virtual until you are really overriding it? I believe it's not a question of being sure or not. Follow the facts: is it overriden somewhere? No? Then it must not be virtual.

为什么要声明一些虚拟的东西,直到你真的重写它为止?我相信这不是一个肯定与否的问题。遵循事实:它是否覆盖某处?没有?那它一定不是虚拟的。