C++ 多态构成条件

本文介绍了C++中的多态性,它是面向对象编程的重要特性。多态允许基类指针调用派生类的成员函数,实现一种事物的多种状态。构成多态的条件包括继承关系、相同函数签名以及虚函数的使用。文章通过示例解释了如何利用虚函数实现多态,并强调了构造函数和析构函数的特殊性。同时,讨论了使用虚函数的时机以及多态中的注意事项,如函数头必须完全相同才能构成多态。
摘要由CSDN通过智能技术生成

1. 什么是多态

  多态(Polymorphism),从字面意思理解,就是一种事物具有多种状态,在C++里表示函数具有多种表达。多态一般出现在向上转型里边,也就是将派生类对象赋值给基类对象。我们直接看一个例子,就能明白为什么会出现多态。

#include <iostream>
using namespace std;

class People{
public:
    People(char *name, int age):m_name(name),m_age(age){}
    void show(){cout<<"name:"<<m_name<<", age:"<<m_age<<", no job"<<endl;} //添加virtual让Peter重新上岗

    char *m_name;
    int m_age;
};
class Worker:public People{
public:
    Worker(char* name, int age, float salary):People(name,age),m_salary(salary){}
    void show(){{cout<<"name:"<<m_name<<", age:"<<m_age<<", is a worker, salary:"<<m_salary<<endl;}}
private:
    float m_salary;
};

int main(){
    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:"<<m_name<<", age:"<<m_age<<", no job"<<endl;}
运行结果为:

name:Tom, age:24, no job
name:peter, age:28, is a worker, salary:5200

  成功让Peter重新上岗。

2. 多态的构成条件

  ①首先,要有继承关系,即,发生在基类和派生类之间;
  ②基类和派生类要有相同函数,这个相同,指得是函数名、输入形参、输出都要一样,比重载和遮蔽要求都要高;
  ③在基类成员函数前面添加virtual关键字。

3. 什么时候使用虚函数

  首先,判断函数是不是定义在基类;其次,判断派生类继承的时候会不会修改这个函数,如果不会修改则不需要声明,如果会修改,则可以声明为虚函数。
  这段话还是比较好理解的,多态本意就是一个函数的两种表达,如果派生类中没有修改,那么基类对象调用谁的都一样,就不存在多态了。

4. 注意事项

需要注意的有三点:
  ①函数头必须完全相同才达到多态的条件。如果仅是函数名一样,形参不一样,不会构成多态!
  ②如果定义了在基类中定义了虚函数,但是派生类中并没有能构成多态的函数,那么基类的虚函数它就是个普通成员函数。
  ③如果派生类的成员函数没有构成多态,基类是无论如何都访问不了的。
针对这个三个注意事项,一个例子可以说明,

#include <iostream>
using namespace std;

class A{
public:
    virtual void show(){cout<<"A:show()"<<endl;}
    virtual void show(int m){cout<<"A:show(int)"<<endl;}
};
class B:public A{
public:
    void show(){cout<<"B:show()"<<endl;}
    void show(char *n){cout<<"B:show(float)"<<endl;}
};

int main(){
    A *a = new B();
    a->show();    //输出  B:show()
    a->show(2);   //输出  A:show(int)
    a->show("dddd"); //报错
}

  ④构造函数不会被继承,也不会构成多态。
  ⑤如果自定义析构函数(一般是为了收回内存),尽量将基类析构函数设置为虚函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值