• C++多态与虚拟:运算符重载(Operator Overloading)


      运算符重载:与function overloading异曲同工的是,C++提供所谓的Operator overloading。所谓operators是像  +(加)-(減)*(乘)/(除)>>(位右移)
    <<(位左移)之类的符号,代表一种动作。

      面对operators,我们应该把他想像是一种函数,只不过形式比较特殊罢了。一般函数的参数出现在括号()之中,而operator的参数围绕着一个operator符号(之前或之后),编程语言内置的数据类型(比如整数`int`、浮点数`float`、长整数`long`等)所使用的操作符(比如加法`+`、减法`-`、乘法`*`等)是由语言本身直接提供的,而不是通过任何外部库或模块来实现的。

      C++允许程序员为class type's object设计专门的operators,使objects的操作能够像内建型别的一样的自然而直观。让operator以种形式呈现,但符号不变,这个就是operator overloading。

      Operator overloading的存在一下褒贬不一,支持者认为它使得程序代码变得更精简漂亮,反对者认为容易把程序员搞迷糊掉。但是,我想,谁都不可否认下面这样的程序代码确实是精简漂亮:
      

    复制代码
    CString str1("Hello, I am J.J.Hou, ");
    CString str2("How are you?");
    CString str3 = str1 + str2; // + 是 CString的一个overloaded operator
    // 于是 str3 为 "Hello, I am J.J.Hou, How are you?"
    int i = 5;
    double pi = 3.141592653;
    cout << "i=" << i << " and pi=" << pi << endl;
    // 于是 console 屏幕上出现"i=5 and pi=3.141592653"。
    复制代码

      现在让我示范一个overloaded operator的作法,只要在以下类的代码中加入第18~21行的+号的重载代码,即可完成CPoint的加法运算:

    复制代码
     1 class CPoint{
     2 
     3 public:
     4 
     5    CPoint()
     6    {
     7         _x=0;
     8 
     9    }
    10 
    11     CPoint(float y){
    12 
    13         _x=y;
    14     }
    15     float x(){return _x;}
    16     void  x(float xval){_x=xval;}
    17 
    18     CPoint operator+(const CPoint& pt) const  //对+号进行重载
    19     {
    20         return CPoint(_x+pt._x);
    21     }
    22 
    23 protected:
    24     float _x;
    25 
    26 };
    复制代码

      以operator开头的函数,表示是个运算子。加法运算子需要左右两个运算元(operands),左侧运算元即成为本函数的this指向的对象,右侧运算元则是本函数的参数pt。上述函数代码如果像下面这样表示,会比较清晰,但两者其实是相同的(因为this指针是个隐藏参数):

        CPoint operator+(const CPoint& pt) const  //对+号进行重载
        {
            return CPoint(this->_x+pt._x);
        }

      有了上述的 CPoint::operator+,现在你可以这么使用它:

    1 CPoint pt1(7.2), pt2(5.3), pt3;
    2 pt3 = pt1 + pt2;
    3 cout << "pt3.x = " << pt3.x() << endl; // 12.5

      C++中,<<和>>是最常用的重载运算符,用于表示对标准输入输出设备(如屏幕和键盘)的读写操作,极大地方便了编程,可替代繁琐的printf()和scanf()函数。这两个运算符在iostream库中定义,为C++编程提供了极大的便利。

      Insertion Operator << for stdout: <<本来是位左移运算符,但是在C++的标准库iostream中被改头换面,其左侧的运算元(operand)被指定为cout(console output device),右侧运算元是一个内建型别的objects。我们可以利用它很方便的对cout连续输出各种内建型别的数据或信息(也是一种objects),不必像C程序那样需要识别不同类型的数据在printf()中的格式符号(如 %s%d%f...):

    1 #include 
    2 ...
    3 int i = 5;
    4 double pi = 3.141592653;
    5 cout << "i=" << i << " and pi=" << f << endl;

      Extraction Operator(>>) for stdin:>>本来是位右移运算符,但在C++标准的iostream中被改头换面,其左侧运算元是cin(console input device),右侧运算元是一个内建型别的object。例如:

    1 #include 
    2 ...
    3 float f;
    4 cout << "f = ? ";
    5 cin >> f;

      程序使用者在健盘上输入,会经由cin装置流往f变量,其作用相当于C runtime library中的scanf()。

     

      Insertion Operator << for file:就像iostream支持对user‘s terminal的输入输出一样,c++另有一组class types支持对文件的输入输出:

      1.ifstream衍生自istream,支持文件的输入。

      2.ofstream衍生自 ostream,支持文件的输出。

      3. fstream衍生自 iostream 支持文件的输入输出

      如果需要这些class type,必须导入对应的header file。请注意,fstream已经含有iostream,所以不需要重复导入;

      下面是信息输入到文件的案例:

    复制代码
    #0001 #include  // include iostream.h
    #0002
    #0003 int main()
    #0004 {
    #0005   cout << "All your keyboard input in monitor "
    #0006       << "will into copy.txt.\n"
    #0007       << "Terminate by ^Z\n\n";
    #0008
    #0009   ofstream outFile("copy.txt");
    #0010   if (!outFile) {
    #0011     cout << "Cannnot open copy.txt for output" << endl;
    #0012     return -1;
    #0013   }
    #0014
    #0015   char c;
    #0016   while (cin.get(c)) // get each char from keyboard
    #0017   outFile << c; // outFile.put(c) 亦 可
    #0018
    #0019   return 0;
    #0020 }
    复制代码

      当程序执行后,会先提示输入,然后接收所有来自于键盘的字符,一一放进”copy.txt"文件中,直到接收到^z 才停止。

      Extraction Operator >> for file:下面是将文件的内案输出到屏幕上的示例:

    复制代码
    #0001 #include  // include iostream.h
    #0002
    #0003 int main()
    #0004 {
    #0005   cout << "All text in copy.txt "
    #0006   << "will stream into monitor.\n\n";
    #0007
    #0008   ifstream inFile("copy.txt");
    #0009   if (!inFile) {
    #0010     cout << "Cannnot open copy.txt for input" << endl;
    #0011     return -1;
    #0012   }
    #0013
    #0014   char c;
    #0015   while (inFile.get(c)) // get each char from file
    #0016   cout.put(c); // output to monitor
    #0017
    #0018   return 0;
    #0019 }
    复制代码

      当程序执行后,会先给一个提示,然后从文件 "copy.txt" 中一一读出每一个字符,显示于屏幕上。上述第0015行如果改为while (inFile >> c) // get each char from file,虽然也能读出字符,但空格会被忽略,这个并非我们所想要的。

  • 相关阅读:
    java常用集合之Set
    分布式 PostgreSQL 集群(Citus),分布式表中的分布列选择最佳实践
    R语言拟合ARIMA模型并使用拟合模型进行预测推理、使用autoplot函数可视化ARIMA模型预测结果(返回的对象为ggplot2对象)
    定制ASP.NET 6.0的应用配置
    windows安装maven,配置环境变量
    Linux系统挂载
    springboot昆明学院档案管理系统 毕业设计-附源码311758
    最新HTML设计搜索表单
    Github上哪些好用的工具
    项目经理年终夜话:我的“第二年状态”
  • 原文地址:https://www.cnblogs.com/ruanchunyi/p/18158775