【问题标题】:Redefining vs. Overriding in C++在 C++ 中重新定义与覆盖
【发布时间】:2014-12-31 20:46:02
【问题描述】:

我对派生类中重新定义和覆盖函数之间的区别感到困惑。

我知道 - 在 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);

【问题讨论】:

  • 重写有助于类多态性。重载有利于功能多态性。重新定义两者都没有,而且是一个错误。

标签: c++ class inheritance base derived


【解决方案1】:

以下是一些基本区别:

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

重写函数是子类中的方法,其定义与祖先类中的虚函数不同。编译器根据用于调用函数的对象的类型来选择所需的函数。

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

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

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

【讨论】:

  • 谢谢,这可能很愚蠢,但这意味着什么:对象引用的静态类型。
  • 函数只有在相同的范围内才会重载。可能要添加。
  • “编译器根据用于调用函数的对象的类型来选择所需的函数。” 这是不正确的,编译器不会做出任何决定。该决定是在运行时通过 vtable 查找完成的。
  • @YelizavetaYR 如果 B 类派生自 A 类并且我们有 A MyA;和 B MyB;并做 MyA=MyB;然后 MyA 的静态类型是 A,而现在(动态)MyA 正在存储 B(其动态类型是 B)。如果我们后者有从 B 派生的 C 类并且有 C MyC;并执行 MyA = MyC,MyA 的动态类型再次变为 C。MyA 的静态类型继续为 A。
  • “重新定义的函数是后代类中的方法,它与祖先类中的非虚函数具有不同的定义。不要这样做。”它可以防止 vtable 查找,并且语言允许这样做,如果收益是值得的。当然,实现应该注意提到的陷阱。
猜你喜欢
  • 1970-01-01
  • 2013-04-18
  • 2012-02-16
  • 2022-01-02
  • 2011-04-14
  • 2014-02-15
  • 2019-01-06
  • 2011-02-26
  • 2011-05-26
相关资源
最近更新 更多