1. 什么是多态
多态(Polymorphism),从字面意思理解,就是一种事物具有多种状态,在C++里表示函数具有多种表达。多态一般出现在向上转型里边,也就是将派生类对象赋值给基类对象。我们直接看一个例子,就能明白为什么会出现多态。
#includeusing namespace std; class People{ public: People(char *name, int age):m_name(name),m_age(age){} void show(){cout<<"name:"< public: Worker(char* name, int age, float salary):People(name,age),m_salary(salary){} void show(){{cout<<"name:"< People *p1 = new People("Tom",24); p1->show(); Worker p2("peter",28,5200.0); p1 = &p2; p1->show(); } 输出: name:Tom, age:24, no job name:peter, age:28, no job
在这个例子里,首先定义了一个People类,包含姓名年龄,而且会显示为no job(无业),然后又定义了一个Worker,是People的派生类,会显示is a worker以及薪水。
在main()函数里,我们首先将People实例化为p1,此时正常显示,Tom是个无业游民,然后Worker类的p2赋值给p1,发现显示Peter也是无业游民,但实际上Peter是一个worker,有薪水的。
通过观察不难发现,派生类赋值给基类指针之后,基类指针指向派生类对象,可以使用其成员变量,刚才姓名和年龄能正常显示就是证明;但是却无法使用派生类的成员函数,使用的还是基类的成员函数。这是因为,指针对象依靠指向调用成员变量,依靠类别调用成员函数,在执行语句p1 = &p2之后,p1类别为People类,而指向p2(Worker类),所以就出现了使用派生类成员变量和基类成员函数的情况。
为了让Peter重新上岗,我们需要借助虚函数,在People类的show()函数前边添加关键字virtual,即
virtual void show(){cout<<"name:"<
name:Tom, age:24, no job name:peter, age:28, is a worker, salary:5200
成功让Peter重新上岗。
2. 多态的构成条件
①首先,要有继承关系,即,发生在基类和派生类之间;
②基类和派生类要有相同函数,这个相同,指得是函数名、输入形参、输出都要一样,比重载和遮蔽要求都要高;
③在基类成员函数前面添加virtual关键字。
3. 什么时候使用虚函数
首先,判断函数是不是定义在基类;其次,判断派生类继承的时候会不会修改这个函数,如果不会修改则不需要声明,如果会修改,则可以声明为虚函数。
这段话还是比较好理解的,多态本意就是一个函数的两种表达,如果派生类中没有修改,那么基类对象调用谁的都一样,就不存在多态了。
4. 注意事项
需要注意的有三点:
①函数头必须完全相同才达到多态的条件。如果仅是函数名一样,形参不一样,不会构成多态!
②如果定义了在基类中定义了虚函数,但是派生类中并没有能构成多态的函数,那么基类的虚函数它就是个普通成员函数。
③如果派生类的成员函数没有构成多态,基类是无论如何都访问不了的。
针对这个三个注意事项,一个例子可以说明,
#includeusing namespace std; class A{ public: virtual void show(){cout<<"A:show()"< cout<<"A:show(int)"< public: void show(){cout<<"B:show()"< cout<<"B:show(float)"< A *a = new B(); a->show(); //输出 B:show() a->show(2); //输出 A:show(int) a->show("dddd"); //报错 }
④构造函数不会被继承,也不会构成多态。
⑤如果自定义析构函数(一般是为了收回内存),尽量将基类析构函数设置为虚函数。



