问题 在C ++中重新定义与覆盖


我对派生类中重新定义和重写函数之间的差异感到困惑。

我知道 - 在C ++中,重新定义的函数是静态绑定的,并且重写的函数是动态绑定的,并且重写了虚函数,并重新定义了非虚函数。

当派生类“重新定义”基类中的方法时,会考虑重新定义。但是当派生类是虚拟的时,它不再重新定义而是覆盖。所以我理解规则的后勤,但我不明白底线。

在下面的示例中,重新定义了SetScore函数。但是,如果我在基类虚拟中设置setScore函数(通过向其添加单词virtual),将覆盖派生类中的setScore。我不明白底线 - 有什么区别。在setScore?

基类:

class GradedActivity
{
protected:
   char letter;            // To hold the letter grade
   double score;           // To hold the numeric score
   void determineGrade();  // Determines the letter grade
public:
   // Default constructor
   GradedActivity()
  { letter = ' '; score = 0.0; }

 // Mutator function
   void setScore(double s) 
      { score = s;
        determineGrade();}

   // Accessor functions
   double getScore() const
      { return score; }

       char getLetterGrade() const
      { return letter; }
};

派生类:

class CurvedActivity : public GradedActivity
{
protected:
   double rawScore;     // Unadjusted score
   double percentage;   // Curve percentage
public:
   // Default constructor
   CurvedActivity() : GradedActivity()
      { rawScore = 0.0; percentage = 0.0; }

   // Mutator functions
   void setScore(double s) 
      { rawScore = s;
        GradedActivity::setScore(rawScore * percentage); }

   void setPercentage(double c)
      { percentage = c; }

   // Accessor funtions
   double getPercentage() const
      { return percentage; }

   double getRawScore() const
      { return rawScore; }
};

这是主要的:

   // Define a CurvedActivity object.
   CurvedActivity exam;

   ... 

   // Send the values to the exam object.
   exam.setPercentage(percentage);
   exam.setScore(numericScore);

11627
2017-11-04 20:03


起源

覆盖有助于类多态。重载有助于功能多态。重新定义既不会也不会出错。 - orfdorf


答案:


以下是一些基本差异:

一个 超载 function是一个函数,它与一个或多个其他函数共享其名称,但具有不同的参数列表。编译器根据使用的参数选择所需的函数。

一个 覆盖 function是后代类中的方法,其定义与祖先类中的虚函数不同。编译器根据用于调用函数的对象的类型选择所需的函数。

一个 重新定义 function是后代类中的方法,其定义与祖先类中的非虚函数不同。不要这样做。由于该方法不是虚拟的,因此编译器根据对象引用的静态类型而不是对象的实际类型来选择要调用的函数。

  • 静态类型检查 表示在编译时进行类型检查。在这种情况下,在运行时不使用类型信息。

  • 动态类型检查 在运行时使用类型信息时发生。 C ++使用一种称为RTTI(运行时类型信息)的机制来实现它。使用RTTI的最常见示例是dynamic_cast运算符,它允许向下转换多态类型:


16
2017-11-04 20:07



谢谢,这可能是愚蠢但这意味着什么:对象引用的静态类型。 - YelizavetaYR
如果在相同的范围内,函数只会重载。可能想补充一点。 - Deduplicator
“编译器根据用于调用函数的对象类型选择所需的函数。” 这不正确,编译器不做任何决定。决定是在运行时通过vtable查找完成的。 - Manu343726
@YelizavetaYR如果B级来自A级,我们有A MyA;和B MyB;做MyA = MyB;然后,静态类型的MyA是A,而现在(动态)MyA正在存储B(其动态类型是B)。如果我们后者的C级来自B并且有C MyC;并且MyA = MyC,MyA的动态类型再次变为C.静态类型的MyA继续为A. - Kae