C++语言-04-重载

相关概念

  • 重载
    • 在同一作用域中为某个函数和运算符指定多个定义,分别成为函数重载和运算符重载
  • 重载声明
    • 与之前已经在作用域内声明过的函数或方法具有相同名称的声明,参数列表和定义不同
  • 重载决策
    • 调用一个重载函数或重载运算符时,编译器需要比较调用函数时的参数类型与定义时的参数类型,来选择最合适的重载函数和重载运算符,这个过程称为重载决策

函数重载

  • 规则
    • 函数名相同
    • 参数列表不同
    • 与返回类型无关
  • 示例

    // 两个整数相加
    int sum(int a, int b) {
        cout << "sum of two int number: " << a + b << endl;
        return a + b;
    }
    // 两个双精度小数相加
    double sum(double a, double b) {
        cout << "sum of two double number: " << a + b << endl;
        return a + b;
    }
    int main(int argc, const char * argv[]) {
        sum(1, 2); // 两个整数相加
        sum(1.0, 2.0); // 两个双精度小数相加
        sum(1, 2.0); //Call to 'sum' is ambiguous
        return 0;
    }

运算符重载

  • 运算符的实质
    • 带有特殊名称的函数
  • 不可重载的运算符

    运算符 含义
    :: 作用于解析运算符
    .* 成员对象选择运算符
    . 以对象方式访问成员运算符
    ?: 条件判断运算符
  • 示例
    • 一元运算符++
      • 具有前缀形式和后缀形式,前缀形式的运算符重载函数没有参数,后缀形式的运算符重载函数具有参数
      // 创建一个Apple的类
      class AppleBasket {
      private:
          double appleWeight; // 苹果的重量
          double priceOfPerKg; // 每千克苹果的价格
          double totalPrices; // 苹果的总价格
      public:
          // set、get方法
          void setAppleWeight(double weight) {
              appleWeight = weight;               
          }
          double getAppleWeight() {
              return appleWeight;
          }
          void setPriceOfPerKg(double price) {
              priceOfPerKg = price;               
          }
          double getPriceOfPerKg() {
              return priceOfPerKg;
          }
          double getTotalPrices() {
              if (totalPrices == 0) { // 不打折
                  totalPrices = appleWeight * priceOfPerKg;
              }
              return totalPrices;
          }
          // 构造方法
          AppleBasket() {
              appleWeight = 0;
              priceOfPerKg = 0;
          }
          AppleBasket(double priceOfPer, double weight) {
              appleWeight = weight;
              priceOfPerKg = priceOfPer;
          }
          // 运算符重载
          /** 一筐苹果的重量自增 */
          AppleBasket operator++() { // 前缀
              AppleBasket apple;
              apple.appleWeight = ++this->appleWeight;
              apple.priceOfPerKg = this->priceOfPerKg;
              return apple;
          }
          AppleBasket operator++(int) { // 后缀,参数必须是int
              AppleBasket apple = *this;
              this->appleWeight++;
              return apple;
          }
      };
    • 二元运算符+

      /** 两筐苹果的重量相加 */
      AppleBasket operator+(AppleBasket other) {
          AppleBasket apple;
          apple.appleWeight = this->appleWeight + other.appleWeight;
          apple.priceOfPerKg = this->priceOfPerKg;
          return apple;
      }
    • 赋值运算符=
      • 通常用来创建一个新的对象
      /** 赋值运算符 */
      void operator=(AppleBasket other) {
          appleWeight = other.appleWeight;
          priceOfPerKg = other.priceOfPerKg;
      }
    • 逻辑运算符<

      /** 比较this框苹果的重量是否小于other框苹果的质量 */
      bool operator<(AppleBasket other) {
          if (this->appleWeight < other.appleWeight) {
              return true;
          } else {
              return false;
          }
      }
    • 函数调用运算符
      • 不是创建一种新的函数调用方式
      • 实际上是创建了一个可以传递任意数目参数的运算符函数
      /** 函数调用运算符 */
      AppleBasket operator()(double w, double p, double totalP) {
          AppleBasket apple;
          apple.appleWeight = w;
          apple.priceOfPerKg = p;
          apple.totalPrices = totalP;
          return apple;
      }
    • 类成员访问运算符->
      • 通常用于为一个类赋予“指针”行为
      • 重载的运算符函数,必须是一个成员函数,且返回类型必须是指针或者类的对象
      • 运算符->通常与指针引用运算符*结合使用,用来实现“智能指针”的功能,通过智能指针访问对象,可以执行与普通指针不同的任务
      // Apple类的容器
      class AppleBasketContainer {
      private:
          vector<AppleBasket *> container;
      public:
          void add(AppleBasket *apple) {
              container.push_back(apple);
          }
          // 友元类
          friend class SmartPointer;
      };
      //AppleBasketContainer类的友元类
      class SmartPointer {
      private:
          AppleBasketContainer appleContainer;
          int index;
      public:
          // 构造函数
          SmartPointer(AppleBasketContainer& ac) {
              appleContainer = ac;
              index = 0;
          }
          // 运算符重载
          /** 返回值表示列表结束 */
          bool operator++() { // 前缀版本
              if (index > appleContainer.container.size()) return false;
              if (appleContainer.container[++index] == 0) return false;
              return true;
           }
          bool operator++ (int) { // 后缀版本
              return operator++();
          }
          /** 重载运算符 -> */
          Apple* operator->() {
              if (!appleContainer.container[index]) {
                  cout << "Zero value!";
                  return (Apple*)0;
              }
              return appleContainer.container[index];
          }
      };
    • 输入/输出运算符
      • 通常将运算符重载函数定义为友元函数,使得在不创建对象的情况下调用函数
      // 输入运算符
      friend istream &operator>>(istream &input, AppleBasket &apple) {
          cout << "请输入每kg苹果的价钱:";
          input >> apple.priceOfPerKg;
          cout << "请输入苹果的总重量:";
          input >> apple.appleWeight;
          apple.totalPrices = apple.appleWeight * apple.priceOfPerKg;
          return input;
      }
      // 输出运算符
      friend ostream &operator<<(ostream &output, const AppleBasket &apple) {
          output << "每kg苹果的价格为:" << apple.priceOfPerKg << endl;
          output << "苹果的总重量为:" << apple.appleWeight << endl;
          output << "苹果的总价为:" << apple.totalPrices << endl;
          return output;
      }
    • 下表运算符[]
      • 通常用来增强数组的功能,如:数组越界检查
      // 每个班级中最多的学生个数
      const int MaxStudentCountOfPerTeacher = 45;
      class Student {
      private:
          int studentId;
          int age;
      public:
          // set,get方法
          void setAge(int a) {
              age = a;
          }
          int getAge() {
              return age;
          }
          // studentId通常是自增的,不暴露set方法
          int getStudentId() {
              return studentId;
          }
          // 设置Teacher为Student的友元类,使Teacher可以访问Student的私有成员
          friend class Teacher;
      };
      class Teacher {
      private:
          Student students[MaxStudentCountOfPerTeacher];
      public:
          // 构造函数
          Teacher() {
              for (int i = 0; i < 45; i++) {
                  students[i].studentId = i + 1;
              }
          }
          // 运算符重载(数组越界检查)
          Student operator[](int i) {
              if (i >= MaxStudentCountOfPerTeacher) {
                  cout << "Index out of bounds" << endl;
                  return students[0];
              }
              return students[i];
          }
      };
  • 重载运算符的简单使用

    // 重载运算符的使用示例
    int main(int argc, const char * argv[]) {
        const int size = 10;
        AppleBasket apples[size];
        AppleContainer appleContainer;
        // 初始化apples与appleContainer
        for (int i = 0; i < size; i++) {
            apples[i].setAppleWeight(i);
            apples[i].setPriceOfPerKg(8.8);
            appleContainer.add(&apples[i]);
        }
        // 创建一个迭代器
        SmartPointer smartPointer(appleContainer);
        do {
            double totalPrice = smartPointer->getTotalPrices();
            cout << "苹果的总价格为:" << totalPrice << endl;
        } while (smartPointer++);
        // 自增运算符++(前缀)
        cout << "第一筐苹果的总价格为:" << (++apples[0]).getTotalPrices() << endl;
        // 自增运算符++(后缀)
        cout << "第二筐苹果的总价格为:" << (apples[0]++).getTotalPrices() << endl;
        // 运算符+
        cout << "前两筐苹果的总价为:" << (apples[0] + apples[1]).getTotalPrices() << endl;
        // 逻辑运算符<
        if (apples[0] < apples[1]) {
            cout << "第一筐苹果的重量小于第二筐苹果的重量" << endl;
        } else {
            cout << "第一筐苹果的重量大于等于第二筐苹果的重量" << endl;
        }
        // 赋值运算符=
        AppleBasket apple = apples[2];
        cout << "第三筐苹果的重量为:" << apple.getAppleWeight() << endl;
        // 函数调用运算符()
        cout << "3kg苹果打折后的价格为:" << apple(3, 8.8, 20.0).getTotalPrices() << endl;
        // 输入输出运算符<<,>>
        cin >> apple;
        cout << apple;
        // 下标运算符[]
        Teacher teacher;
        Student student;
        student = teacher[MaxStudentCountOfPerTeacher - 1];
        cout << "最后一个学生的学号为:" << student.getStudentId() << endl;
        student = teacher[MaxStudentCountOfPerTeacher];
        cout << student.getStudentId() << endl;
        return 0;
    }

你可能感兴趣的:(C++语言-04-重载)