多态性
一、运算符重载
运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。
1、运算符重载的规则
(1)C++种的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已经有的运算符。
(2)重载之后的运算符的优先级和结核性都不会改变。
(3)运算符重载时针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来讲,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。
C++标准规定,有些操作符是不能重载的,它们是类属关系运算符"."、成员指针运算符".*"、作用域分辨符"::"和三目运算符"?:"。
前面两个运算符保证了C++中访问成员功能的含义不被改变。作用域分辨符的操作是类型,而不是普通的表达式,也不具备重载的特征。
运算符的重载形式:
返回类型 operator 运算符(形参表) { 函数体 }
重载为类的成员函数和重载为非成员函数的声明方式不同。
2、运算符重载的实例
对类Point重载“++”(自增)、“--”(自减)“、运算符,要求同时重载前缀和后缀的形式
#include <iostream> using namespace std; class Point { public: Point(int xx = 0, int yy = 0):x(xx),y(yy){} int getX() { return x; } int getY() { return y; } Point operator++(); Point operator++(int); Point operator--(); Point operator--(int); private: int x; int y; }; Point Point::operator++() { x++; y++; return *this; } Point Point::operator++(int) { Point old = *this; ++(*this); return old; } Point Point::operator--() { x--; y--; return *this; } Point Point::operator--(int) { Point old = *this; --(*this); return old; } int main() { Point a,b; cout << "a 的值为:" << a.getX() << " , " << a.getY() << endl; cout << "b 的值为:" << b.getX() << " , " << b.getY() << endl; b = --a; cout << "a 的值为:" << a.getX() << " , " << a.getY() << endl; cout << "b 的值为:" << b.getX() << " , " << b.getY() << endl; b = ++a; cout << "a 的值为:" << a.getX() << " , " << a.getY() << endl; cout << "b 的值为:" << b.getX() << " , " << b.getY() << endl; b = a++; cout << "a 的值为:" << a.getX() << " , " << a.getY() << endl; cout << "b 的值为:" << b.getX() << " , " << b.getY() << endl; b = a--; cout << "a 的值为:" << a.getX() << " , " << a.getY() << endl; cout << "b 的值为:" << b.getX() << " , " << b.getY() << endl; return 0; }
运算结果
二、虚函数
1、虚函数使用规则
一般虚函数的声明方法是:
virtual 函数类型 函数名(形参表);
这实际上就是在类的定义中使用virtual关键字来限定成员函数,虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。
运行过程中的多态需要满足三个条件:
1、类之间满足赋值兼容规则。
2、要声明虚函数。
3、由成员函数来调用或者是通过指针、引用来访问虚函数。
在一个程序中,如果派生类并没有显式给出虚函数声明,这时系统就会遵循以下规则来判断派生类的一个函数成员是不是虚函数。
- 该函数是否与基类的虚函数有相同的名称。
- 该函数是否与基类的虚函数有相同的参数个数及相同的对应参数类型。
- 该函数是否与基类的虚函数有相同的返回值或者满足赋值兼容规则的指针、引用型的返回类型。
如果从名称、参数及返回值3个方面检查之后,派生类的函数满足了上述条件,就会自动确定虚函数。这是,派生类的虚函数便覆盖了基类的虚函数。不仅如此,派生类中的虚函数还会隐藏基类中同名函数的所有其他重载形式。
2、虚函数使用实例
编写一个哺乳动物类Mammal,在由此派生出狗类Dog,二者都有声明speak()成员函数,该函数在基类中被声明为虚函数。声明一个Dog类的对象,通过此对象调用speak函数,观察运行结果。
#include <iostream> using namespace std; class Mammal { public: //在使用指向子类对象的基类指针,并调用子类中的覆盖函数时, //如果该函数不是虚函数,那么将调用基类中的该函数;如果该函数是虚函数,则会调用子类中的该函数。 virtual void speak() { cout << "Mammal speak" << endl; } //void speak() { cout << "Mammal speak" << endl; } }; class Dog:public Mammal { public: void speak() { cout << "汪" << endl; } }; int main() { Mammal *p = new Dog; p->speak(); }
运行结果
三、总结
1、多态提高了代码的维护性(继承保证)
2、多态提高了代码的扩展性(由多态保证)