Переопределение и переопределение в C++

Меня смущают различия между переопределением и переопределением функций в производных классах.

Я знаю, что в С++ переопределенные функции статически связаны, а переопределенные функции связаны динамически, и что виртуальная функция переопределяется, а не виртуальная функция переопределяется.

Когда производный класс «переопределяет» метод в базовом классе, он считается переопределением. Но когда производный класс является виртуальным, он больше не переопределяет, а переопределяет. Итак, я понимаю логистику правил, но не понимаю сути.

В приведенном ниже примере функция SetScore переопределена. Однако, если я сделаю функцию setScore в базовом классе виртуальной (добавив к ней слово virtual), 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);

person YelizavetaYR    schedule 04.11.2014    source источник
comment
Переопределение облегчает полиморфизм классов. Перегрузка способствует функциональному полиморфизму. Переопределение не делает ни того, ни другого и является ошибкой.   -  person orfdorf    schedule 04.11.2014


Ответы (1)


Вот несколько основных отличий:

Перегруженная функция — это функция, которая имеет то же имя, что и одна или несколько других функций, но имеет другой список параметров. Компилятор выбирает нужную функцию на основе используемых аргументов.

Переопределенная функция – это метод в классе-потомке, определение которого отличается от определения виртуальной функции в классе-предке. Компилятор выбирает нужную функцию на основе типа объекта, используемого для вызова функции.

Переопределенная функция – это метод в классе-потомке, определение которого отличается от определения невиртуальной функции в классе-предке. Не делай этого. Поскольку метод не является виртуальным, компилятор выбирает, какую функцию вызывать, основываясь на статическом типе ссылки на объект, а не на фактическом типе объекта.

  • Статическая проверка типов означает, что проверка типов выполняется во время компиляции. В этом случае информация о типе не используется во время выполнения.

  • Динамическая проверка типов происходит, когда информация о типах используется во время выполнения. C++ использует механизм, называемый RTTI (информация о типе времени выполнения), чтобы реализовать это. Наиболее распространенным примером использования RTTI является оператор dynamic_cast, который позволяет выполнять понижающее приведение полиморфных типов:

person Lawrence Aiello    schedule 04.11.2014
comment
Спасибо, это может быть глупо, но что это значит: статический тип ссылки на объект. - person YelizavetaYR; 04.11.2014
comment
Функции перегружаются только в том случае, если они находятся в той же области. Возможно, вы захотите добавить это. - person Deduplicator; 04.11.2014
comment
Компилятор выбирает нужную функцию на основе типа объекта, используемого для вызова функции. Это неверно, компилятор ничего не решает. Решение принимается во время выполнения с помощью поиска в vtable. - person Manu343726; 04.11.2014
comment
@YelizavetaYR Если класс B является производным от класса A и у нас есть A MyA; и В MyB; и сделать MyA=MyB; Тогда статический тип MyA — это A, а прямо сейчас (динамически) MyA хранит B (его динамический тип — B). Если мы последний имеем класс C, производный от B, и имеем C MyC; и сделать MyA = MyC, еще раз динамический тип MyA изменился на C. Статический тип MyA продолжает быть A. - person Kae; 04.11.2014