我们知道如何在遵循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++.