zoukankan      html  css  js  c++  java
  • 运算符重载

    我们知道如何在遵循C++语法条件下实现"虚函数、重载运算符函数"。

    我认为当我们尝试来实现重载运算符的虚函数时需要知道:函数签名、redefine、overload、override、虚表、RTTI、编译器默认的插入行为。(此处没有使用虚基类,因此不需要虚表表的知识)

    和 同学 以及 ”EA娘家人“分别讨论了这个问题,均没有得出详细的解答,不知到android源码中有没有,没仔细找。

    参考:

    http://stackoverflow.com/questions/669818/virtual-assignment-operator-c

    http://www.icu-project.org/docs/papers/cpp_report/the_assignment_operator_revisited.html

    http://www.cplusplus.com/forum/beginner/18705/

    《C++ Primer》4ed_CN    p_646~652

    要求:

    1、派生类继承自基类,派生类与派生类相加时可以完成派生类实例中相应成员(包括继承自基类中的成员)的相加。(这个简单)

    2、基类的指针指向一个派生类的实例,通过调用重载“+”运算符函数,使得通过基类的指针可以完成与另一个派生类实例的加法。

    关于第1点我们很容实现,只要在派生类的operator+中主动调用基类的operator+就可以了;

    关于第2点,我想如果可以通过基类的指针直接调用派生类的operator+就可以了,但是如果要这样做就需要:(1)operator+为虚函数;(2)派生类的operatpr+的形参类型与基类的operator+的形参类型完全相同;这里面的第二个要求固然可以实现,但是个人感觉不好,代码的可读性也较差。

    关于第2点,我的想法是:operator+不声明为虚函数,相应的类类型的指针都在编译时即确定调用各自类类型的operator+函数。在各自的operator+中调用一个虚函数来完成加法函数,每次调用该虚函数就会调用最终派生类的相应虚函数(通过虚表实现),再在派生类的虚函数中依次显式的调用上一级的相应的虚函数。

    如下是我的解法,开销是大了点……

      1 #include <iostream>                                                                                                
      2 #include <typeinfo>
      3 using namespace std;
      4 
      5 class BASE
      6 {
      7     private:
      8         int i;  
      9     protected:
     10         virtual const BASE& ADD(const BASE& thiz)
     11         {       
     12             cout << "BASE ADD" << endl;
     13             i += thiz.i; 
     14             return *this;
     15         }       
     16 
     17         virtual const BASE& ASSIGN(const BASE& thiz)
     18         {       
     19             cout << "BASE ASSING" << endl;
     20             i = thiz.i; 
     21             return *this;
     22         }       
     23 
     24     public: 
     25         BASE(void):i(1)
     26         {       
     27             cout << "BASE constructor" << endl;
     28         }       
     29 
     30         virtual ~BASE(void)
     31         {       
     32             cout << "BASE deconstructor" << endl;
     33         }       
     34 
     35         const BASE& operator + (const BASE& thiz)
     36         {       
     37             cout << "BASE operator +" << endl;
     38             if (typeid(*this) != typeid(thiz))
     39                 return *this;
     40 
     41             ADD(thiz);
     42 
     43             return *this;
     44         }
     45 
     46         const BASE& operator = (const BASE& thiz)
     47         {
     48             cout << "BASE operator =" << endl;
     49             if (typeid(*this) != typeid(thiz))
     50                 return *this;
     51 
     52             ASSIGN(thiz);
     53 
     54             return *this;
     55         }
     56 };
     57 
     58 class DERIVE: public BASE
     59 {
     60     private:
     61         int j;
     62     protected:
     63         const DERIVE& ADD(const BASE& thiz)
     64         {
     65             BASE::ADD(thiz);
     66             cout << "DERIVE ADD" << endl;
     67             const DERIVE &org = dynamic_cast<const DERIVE&>(thiz);
     68             j += org.j;
     69             return *this;
     70         }
     71 
     72         const DERIVE& ASSIGN(const BASE& thiz)
     73         {
     74             BASE::ASSIGN(thiz);
     75             cout << "DERIVE ASSING" << endl;
     76 
     77             const DERIVE &org = dynamic_cast<const DERIVE&>(thiz);
     78             j = org.j;                                                                                             
     79             return *this;
     80         }
     81 
     82     public:
     83         DERIVE(void):j(2)
     84         {
     85             cout << "DERIVE constructor" << endl;
     86         }
     87 
     88         ~DERIVE(void)
     89         {
     90             cout << "DERIVE deconstructor" << endl;
     91         }
     92 
     93         const DERIVE& operator + (const DERIVE& thiz)
     94         {
     95             cout << "DERIVE operator +" << endl;
     96             if (typeid(*this) != typeid(thiz))
     97                 return *this;
     98 
     99             ADD(thiz);
    100 
    101             return *this;
    102         }
    103 
    104         const DERIVE& operator = (const DERIVE& thiz)
    105         {
    106             cout << "DERIVE operator =" << endl;
    107             if (typeid(*this) != typeid(thiz))
    108                 return *this;
    109 
    110             ASSIGN(thiz);
    111 
    112             return *this;
    113         }
    114 };
    115 
    116 int main(void)
    117 {
    118     DERIVE one;
    119     cout << "1" << endl;
    120     DERIVE two;
    121     cout << "2" << endl;
    122 
    123     one = one + two;
    124     cout << "3" << endl;
    125 
    126     BASE *p = &one;
    127     p->operator+(two);
    128     cout << "4" << endl;
    129 
    130     return 0;
    131 }

    运行结果

     1 BASE constructor
     2 DERIVE constructor
     3 1
     4 BASE constructor
     5 DERIVE constructor
     6 2
     7 DERIVE operator +
     8 BASE ADD
     9 DERIVE ADD
    10 DERIVE operator =
    11 BASE ASSING
    12 DERIVE ASSING
    13 3
    14 BASE operator +
    15 BASE ADD
    16 DERIVE ADD
    17 4
    18 DERIVE deconstructor
    19 BASE deconstructor
    20 DERIVE deconstructor
    21 BASE deconstructor

     记录下一段话,我们应该慎重地完成重载的等号运算符虚函数:

      A virtual assignment operator is allowed, but is complex to create correctly. The danger is that you might assign a base class to a derived class, causing inconsistent vaues in the derived class's data members. Attempting virtual assignment is best left until you are more experienced in C++.

  • 相关阅读:
    prepareStatement的用法和解释
    java socket报文通信(一) socket的建立
    java多线程小结
    Java_XML操作
    socket实例2
    socket实例1
    Socket小结
    从源码角度理解android动画Interpolator类的使用
    android使用属性动画代替补间动画
    OKHttp的简单使用
  • 原文地址:https://www.cnblogs.com/openix/p/3259746.html
Copyright © 2011-2022 走看看