一、多态的实现
- 绑定机制:
绑定是将一个标识符名和一个存储地址联系在一起的过程
- 编译时的多态通过静态绑定实现
绑定工作在程序编译连接阶段运行
- 运行时的多态通过动态绑定实现
绑定工作在程序运行阶段运行
二、运算符重载(静态绑定)
函数重载同样也是静态绑定
1. 重载为类成员函数
1 2 3
| 函数类型 operator 运算符(形参) { ...... }
|
参数个数=原操作数个数-1 (后置++,– 除外)
双目运算符重载规则 (1个参数 对象)
重载B为类成员函数,使之能够实现 oprd1 B oprd2;
以 +
举例
经重载后,表达式 a + b
相当于 a.operator +(b)
1 2 3 4 5
| Complex operator + (const Complex &c2) const;
Complex Complex::operator+(const Complex &c2){ return Complex(real + c2.real, imag + c2.imag);
|
前置单目运算符重载规则(无参)
重载B为类成员函数,使之能实现 B oprd,无形参
以 前置++
为例:
经重载后,++ a
相当于 a.operaotr ++()
1 2 3 4 5 6 7 8
| Point &operator++();
Point &Point::operator++(){ x++; y++; return *this; }
|
后置单目运算符++和–重载规则 (1个参数 int)
如果要重载 ++ 或者 – 为类成员函数,使之能够实现表达式 oprd ++ 或 oprd –,其中oprd为A类对象,则 ++ Huon – 应该被重载为A类的成员函数,且具有一个 int 形参
以 后置++
为例:
经重载后,a ++
相当于 a.operaotr ++(0)
1 2 3 4 5 6 7 8 9 10
| Point operator++(int);
Point Point::operator++(int) { Point temp = *this; ++*this; return temp; }
|
2. 重载为非成员函数
参数个数=原操作数个数(后置++,– 除外)
双目运算符重载规则(2个参数 对象)
两个操作数都是类的引用
1
| friend Complex operator + (const Complex &c1, const Complex &c2);
|
前置单目运算符重载规则 (1个参数 对象)
1
| friend Complex operator ++(Complex &c1);
|
后置单目运算符++和–重载规则 (2个参数 对象,0)
1
| friend Complex operator ++(Complex &c1, 0);
|
三、运算符重载实例
① 对Point类重载++(自增)、–(自减)运算符,同时重载前缀和后缀形式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| class Point { private: int x, y; public: Point(int a, int b) { x = a; y = b; } Point &operator++(); Point operator++(int); Point &operator--(); Point operator--(int); int getx() { return x; } int gety() { return y; } }; Point &Point::operator++() { x++; y++; return *this; } Point Point::operator++(int) { Point temp = *this; ++*this; return temp; } Point &Point::operator--() { x--; y--; return *this; } Point Point::operator--(int) { Point temp = *this; --*this; return temp; }
|
② 高精度算法:定义HugeInt类能处理20亿以上的整数并重载+和<<
32位整数的机器所能表示的整数范围大概是-20亿~20亿
思路:将大数存入数组,再对数组进行逐位操作
代码实现:👇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <cstring> #include <string> #include <iostream> using std::ostream;
class HugeInt { public: HugeInt(long val = 0); HugeInt(const char *s); HugeInt operator +(HugeInt &rhs); friend ostream &operator <<(ostream &os, HugeInt &rhs); private: short integer[30]; };
HugeInt::HugeInt(long val) { for (int i = 0; i <= 29; i++) integer[i] = 0; for (int i = 29; val != 0 && i >= 0; i --) { integer[i] = val % 10; val /= 10; } } HugeInt::HugeInt(const char *s) { for (int i = 0; i <= 29; i++) integer[i] = 0; for (int i = 30 - strlen(s), j = 0; i <= 29; i++, j++) integer[i] = s[j]-'0'; }
HugeInt HugeInt::operator +(HugeInt &op2) { HugeInt temp; int carry = 0; for (int i = 29; i >= 0; i--) { temp.integer[i] = integer[i] + op2.integer[i] + carry; if (temp.integer[i] > 9) { temp.integer[i] %= 10; carry = 1; } else carry = 0; } return temp; } ostream &operator <<(ostream &output, HugeInt &num) { int i = 0; for (; (num.integer[i] == 0) && (i <= 29); i++) ; if (i == 30) output << 0; else for (; i <= 29; i++) output << num.integer[i]; return output; }
int main() { using std::cout; using std::endl; HugeInt n1(7654321),n2(1234567); //测试long型 HugeInt n3("12345678987654321"), n4("12345678987654321"); //测试字符串型 cout << "n1 is " << n1 << "\nn2 is " << n2 << "\nn3 is " << n3 << "\nn4 is " << n4 <<endl; HugeInt n5 = n1+n2; HugeInt n6 = n3+n4; HugeInt n7 = n3 + n1; cout<< "n1+n2="<<n5<<endl; cout<< "n3+n4="<<n6<<endl; cout<< "n1+n3=" << n7 << endl; }
|
四、虚函数(动态绑定)
初始虚函数
多态是不同对象对同一消息有不同的行为特性,虚函数作为运行过程中多态的基础,主要是针对对象的,而构造函数是在对象产生之前运行的,因此虚构造函数没有意义。
一般虚函数成员
virtual 关键字
虚表与动态绑定
虚函数实例
定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass有成员函数fn1()、fn2(),fn1()是虚函数,DerivedClass也有成员函数fn1()、fn2(),在主程序中定义一个DerivedClass的对象,分别用BaseClass和DerivedClass的指针来调用fn1()、fn2(),观察运行结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class BaseClass { public: virtual void fn1(); void fn2(); }; void BaseClass::fn1() { cout << "调用基类的虚函数fn1()" << endl; } void BaseClass::fn2() { cout << "调用基类的非虚函数fn2()" << endl; } class DerivedClass : public BaseClass { public: void fn1(); void fn2(); }; void DerivedClass::fn1() { cout << "调用派生类的函数fn1()" << endl; } void DerivedClass::fn2() { cout << "调用派生类的函数fn2()" << endl; } int main() { DerivedClass aDerivedClass; DerivedClass *pDerivedClass = &aDerivedClass; BaseClass *pBaseClass = &aDerivedClass; pBaseClass->fn1(); pBaseClass->fn2(); pDerivedClass->fn1(); pDerivedClass->fn2(); }
|
五、纯虚函数与抽象类