一、函数重载(Function Overloading)

C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading)。借助重载,一个函数名可以有多种用途。

例:借助函数重载交换不同类型的变量的值

  1. #include <iostream>
  2. using namespace std;
  3. //交换 int 变量的值
  4. void Swap(int *a, int *b){
  5. int temp = *a;
  6. *a = *b;
  7. *b = temp;
  8. }
  9. //交换 float 变量的值
  10. void Swap(float *a, float *b){
  11. float temp = *a;
  12. *a = *b;
  13. *b = temp;
  14. }
  15. //交换 char 变量的值
  16. void Swap(char *a, char *b){
  17. char temp = *a;
  18. *a = *b;
  19. *b = temp;
  20. }
  21. //交换 bool 变量的值
  22. void Swap(bool *a, bool *b){
  23. char temp = *a;
  24. *a = *b;
  25. *b = temp;
  26. }
  27. int main(){
  28. //交换 int 变量的值
  29. int n1 = 100, n2 = 200;
  30. Swap(&n1, &n2);
  31. cout<<n1<<", "<<n2<<endl;
  32. //交换 float 变量的值
  33. float f1 = 12.5, f2 = 56.93;
  34. Swap(&f1, &f2);
  35. cout<<f1<<", "<<f2<<endl;
  36. //交换 char 变量的值
  37. char c1 = 'A', c2 = 'B';
  38. Swap(&c1, &c2);
  39. cout<<c1<<", "<<c2<<endl;
  40. //交换 bool 变量的值
  41. bool b1 = false, b2 = true;
  42. Swap(&b1, &b2);
  43. cout<<b1<<", "<<b2<<endl;
  44. return 0;
  45. }

当实参的类型和形参的类型不一致时情况就会变得稍微复杂,要注意重载过程中的二义性和类型转换。请参考http://c.biancheng.net/view/vip_2207.html

二、运算符重载(Operator Overloading)

实际上,我们已经在不知不觉中使用了运算符重载。例如,+号可以对不同类型(int、float 等)的数据进行加法操作;<<既是位移运算符,又可以配合 cout 向控制台输出数据。C++本身已经对这些运算符进行了重载。C++ 也允许程序员自己重载运算符,这给我们带来了很大的便利。
运算符重载的格式为:

  1. 返回值类型 operator 运算符名称 (形参表列){
  2. //TODO:
  3. }

operator是关键字,专门用于定义重载运算符的函数。我们可以将operator 运算符名称这一部分看做函数名,对于下面的代码,函数名就是operator+。运算符重载是通过函数实现的,它本质上是函数重载。

1)重载+

例:复数类的+重载:

#include <iostream>
using namespace std;

class complex{
public:
    complex();
    complex(double real, double imag);
public:
    //声明运算符重载
    complex operator+(const complex &A) const;
    void display() const;
private:
    double m_real;  //实部
    double m_imag;  //虚部
};

complex::complex(): m_real(0.0), m_imag(0.0){ }
complex::complex(double real, double imag): m_real(real), m_imag(imag){ }

//实现运算符重载
complex complex::operator+(const complex &A) const{
    complex B;
    B.m_real = this->m_real + A.m_real;
    B.m_imag = this->m_imag + A.m_imag;
    return B;
}
void complex::display() const{
    cout<<m_real<<" + "<<m_imag<<"i"<<endl;
}
int main(){
    complex c1(4.3, 5.8);
    complex c2(2.4, 3.7);
    complex c3;
    c3 = c1 + c2;
    c3.display();
    return 0;
}

运行结果:6.7 + 9.5i
上面的例子中,我们在 complex 类中重载了运算符+,该重载只对 complex 对象有效。当执行c3 = c1 + c2;语句时,编译器检测到+号左边(+号具有左结合性,所以先检测左边)是一个 complex 对象,就会调用成员函数operator+(),也就是转换为下面的形式:

c3 = c1.operator+(c2);

将运算符重载函数作为全局函数时,一般都需要在类中将该函数声明为友元函数。原因很简单,该函数大部分情况下都需要使用类的 private 成员。
如上面的例子,若重载函数为全局函数:

complex operator+(const complex &A) const{
    complex B;
    B.m_real = this->m_real + A.m_real;
    B.m_imag = this->m_imag + A.m_imag;
    return B;
}

对应的类中函数声明变成:

//声明为友元函数
friend complex operator+(const complex &A, const complex &B);

到底以成员函数还是全局函数(友元函数)的形式重载运算符,请参考http://c.biancheng.net/view/vip_2310.html
要以全局函数的形式重载 +、-、、/、==、!=,以成员函数的形式重载了 +=、-=、=、/=

2)重载()(函数调用运算符)

函数调用运算符 () 可以被重载用于类的对象。当重载 () 时,不是创造了一种新的调用函数的方式,相反地,这是创建一个可以传递任意数目参数的运算符函数。

例1:(仿函数)


#include <iostream>  

using namespace std;  

class Time  
{  
public:  

    //小括号重载 版本0 
    void operator()()  
    {  
        cout<< "version 0"<<endl;  
    }  


    //小括号重载 版本1  
    void operator()(int h)  
    {  
        cout<< "version 1"<<endl;  
    }  

    //小括号重载 版本2  
    void operator()(int h, int m)  
    {  
        cout<< "version 2"<<endl;  
    }  


};  

int main()  
{  
    Time t;  
    t();    //小括号重载 版本0 

    t(1);   //小括号重载 版本1  

    t(1,1); //小括号重载 版本2  

    return 0;  
}

例2:

#include <iostream>
using namespace std;

class Distance
{
   private:
      int feet;             // 0 到无穷
      int inches;           // 0 到 12
   public:
      // 所需的构造函数
      Distance(){
         feet = 0;
         inches = 0;
      }
      Distance(int f, int i){
         feet = f;
         inches = i;
      }
      // 重载函数调用运算符
      Distance operator()(int a, int b, int c)
      {
         Distance D;
         // 进行随机计算
         D.feet = a + c + 10;
         D.inches = b + c + 100 ;
         return D;
      }
      // 显示距离的方法
      void displayDistance()
      {
         cout << "F: " << feet <<  " I:" <<  inches << endl;
      }

};
int main()
{
   Distance D1(11, 10), D2;

   cout << "First Distance : "; 
   D1.displayDistance();

   D2 = D1(10, 10, 10); // invoke operator()
   cout << "Second Distance :"; 
   D2.displayDistance();

   return 0;
}

结果:

First Distance : F: 11 I:10
Second Distance :F: 30 I:120