Вводный курс по C++||Перегруженные операторы и перегруженные функции C++||Полиморфизм C++

C++ перегруженные операторы и перегруженные функции

C++ перегруженные операторы и перегруженные функции

C++ позволяет указывать несколько определений функции и оператора в одной и той же области видимости , что называется перегрузкой функций и перегрузкой операторов соответственно .

Перегруженное объявление — это объявление с тем же именем, что и у функции или метода, уже объявленного в области видимости, но с другим списком параметров и определением (реализацией).

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

Перегрузка функций в C++

В одной области видимости несколько функций с одним и тем же именем могут быть объявлены с похожими функциями, но формальные параметры (количество, тип или порядок параметров) у этих функций с одним и тем же именем должны быть разными. Вы не можете перегружать функции, просто различаясь типом возвращаемого значения.

В следующем примере одноименная функция  print()  используется для вывода разных типов данных:

#include <iostream>
using namespace std;
 
class printData 
{
   public:
      void print(int i) {
        cout << "Printing int: " << i << endl;
      }

      void print(double  f) {
        cout << "Printing float: " << f << endl;
      }

      void print(string c) {
        cout << "Printing character: " << c << endl;
      }
};

int main(void)
{
   printData pd;
 
   // Call print to print integer
   pd.print(5);
   // Call print to print float
   pd.print(500.263);
   // Call print to print character
   pd.print("Hello C++");
 
   return 0;
}

попробуй

Когда приведенный выше код скомпилирован и выполнен, он дает следующий результат:

Printing int: 5
Printing float: 500.263
Printing character: Hello C++

Перегрузка операторов в C++

Вы можете переопределить или перегрузить большинство встроенных операторов C++. Таким образом, вы можете использовать операторы для пользовательских типов.

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

Box operator+(const Box&);

Объявите оператор сложения, чтобы добавить два объекта Box и вернуть окончательный объект Box. Большинство перегруженных операторов могут быть определены как обычные функции, не являющиеся членами, или как функции-члены класса. Если мы определим вышеуказанную функцию как функцию, не являющуюся членом класса, то нам нужно передать два параметра для каждой операции следующим образом:

Box operator+(const Box&, const Box&);

В следующем примере демонстрируется концепция перегрузки операторов с использованием функций-членов. Здесь объект передается как параметр, а доступ к свойствам объекта   осуществляется с помощью оператора this следующим образом:

#include <iostream>
using namespace std;

class Box
{
   public:

      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }

      void setBreadth( double bre )
      {
          breadth = bre;
      }

      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 Box 对象相加
      Box operator+(const Box& b)
      {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box
   Box Box2;                // 声明 Box2,类型为 Box
   Box Box3;                // 声明 Box3,类型为 Box
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;

   // 把两个对象相加,得到 Box3
   Box3 = Box1 + Box2;

   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;

   return 0;
}

Когда приведенный выше код скомпилирован и выполнен, он дает следующий результат:

Объем коробки 1: 210
Объем Box2: 1560
Объем Box3: 5400

Перегружаемый оператор/неперегружаемый оператор

Ниже приведен список операторов, которые могут быть перегружены:

+ - * / % ^
& | ~ ! , "="
< > <= >= ++ --
<< >> == "=" && ||
+= "=" "=" "=" ^= "="
|= "=" <<= >>= [] ()
-> ->* новый новый [] удалить удалить []

Ниже приведен список неперегружаемых операторов:

:: .* . ?:

Пример перегрузки оператора

Ниже приведены примеры перегрузки различных операторов, которые помогут вам лучше понять концепцию перегрузки.

серийный номер Операторы и экземпляры
1 перегрузка унарного оператора
2 перегрузка бинарного оператора
3 реляционная перегрузка оператора
4 Перегрузка оператора ввода/вывода
5 ++ и -- перегрузка операторов
6 перегрузка оператора присваивания
7 перегрузка оператора вызова функции()
8 Оператор нижнего индекса [] перегружен
9 Оператор доступа к члену класса -> перегружен

Полиморфизм С++

Полиморфизм С++

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

Полиморфизм C++ означает, что при вызове функции-члена выполняются разные функции в зависимости от типа объекта, вызывающего функцию.

В приведенном ниже примере базовый класс Shape является производным от двух классов следующим образом:

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();

   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}

Когда приведенный выше код скомпилирован и выполнен, он дает следующий результат:

Область родительского класса:
Область родительского класса:

Причина неправильного вывода в том, что вызывающая функция area() устанавливается компилятором на версию в базовом классе, это называется статическим полиморфизмом или статическим связыванием  — вызов функции подготавливается до выполнения программы. Иногда это также называют ранним связыванием , потому что функция area() настраивается во время компиляции программы.

А пока давайте немного изменим программу и поместим ключевое слово virtual перед объявлением area() в классе Shape  следующим образом:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

После модификации, когда код предыдущего примера компилируется и выполняется, он дает следующий результат:

Площадь класса прямоугольника
Площадь класса треугольника

В этот момент компилятор смотрит на содержимое указателя, а не на его тип. Поэтому, поскольку адреса объектов классов tri и rec хранятся в *shape, вызываются соответствующие функции area().

Как видите, каждый подкласс имеет независимую реализацию функции area(). Вот как обычно используется полиморфизм . С полиморфизмом у вас может быть несколько разных классов, все с функциями с одинаковыми именами, но разными реализациями, и параметры функций могут быть даже одинаковыми.

виртуальная функция

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

Мы хотим, чтобы в любой точке программы мы могли выбирать, какую функцию вызывать, в зависимости от типа вызываемого объекта.Эта операция называется динамической компоновкой или поздней привязкой .

чисто виртуальная функция

Вы можете захотеть определить виртуальную функцию в базовом классе, чтобы переопределение функции в производном классе больше подходило для объектов, но вы не можете дать осмысленную реализацию виртуальной функции в базовом классе.Используйте чисто виртуальные функции.

Мы можем переписать виртуальную функцию area() в базовом классе следующим образом:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      // pure virtual function
      virtual int area() = 0;
};

= 0 сообщает компилятору, что функция не имеет тела, а приведенная выше виртуальная функция является чисто виртуальной .

Supongo que te gusta

Origin blog.csdn.net/m0_69824302/article/details/130178662
Recomendado
Clasificación