c++关于多态的复习整理

一、静态联编

1、将源代码中的函数调用解释为执行特定的函数代码被称为函数名联编
2、根据函数名选择对应的函数体执行,但是在C++有函数重载所以这必须还要看函数的参数及函数名才能确定使用那个函数
3、这种可以在编译过程就完成的这种编译(静态联编)

#include<iostream>
using namespace std;
class Animal
{
public:
 void eat();
};
class Dog:public Animal
{
public:
 void eat();
};
void Animal::eat()
{
 cout << "animal is eating" << endl;
}
void Dog::eat()
{
 cout << "dog is eating" << endl;
}
void fun(Animal*animal)
{
 animal->eat();
}
int main()
{
 Animal *animal=new Animal;
 fun(animal);
 Dog *dog=new Dog;
 fun(dog);
 system("pause");
 return 0;
}

输出为:
animal is eating
animal is eating

因为在上面的例子中,发生了继承关系,所以在void fun(Animal&animal)函数中,编译器允许进行类型转换,这里的类型转换是当传入dog变量时派生类转为基类,是安全的,因为,派生类继承基类,派生类继承了基类成员,派生类有基类的全部成员,在强制转换为基类时,因为派生类所拥有的内存足够,所以转换为基类时,可以将用不到的部分内存抛弃,所以安全,但是基类转派生类,不安全,因为基类不一定有派生类的成员,因此内存数据较派生类来说太小,强转为派生类时不知道该如何处理派生类中填充后剩余的空间,所以可能会造成错误。

由此我们也可以得出一个道理:派生类可以强转为基类,基类不可以强转为派生类

二、动态联编(多态)

根据程序运行的时候来选择函数使用的方式(动态联编)

通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。

为了防止上例的情况发生,让基类指针能够访问派生类的成员函数,C++ 增加了虚函数(Virtual Function)。使用虚函数只需要在函数声明前面增加 virtual 关键字。

#include<iostream>
using namespace std;
class Animal
{
public:
 virtual void eat();
};
class Dog:public Animal
{
public:
 virtual void eat();
};
void Animal::eat()
{
 cout << "animal is eating" << endl;
}
void Dog::eat()
{
 cout << "dog is eating" << endl;
}
void fun(Animal*animal)
{
 animal->eat();
}
int main()
{
 Animal *animal=new Animal;
 fun(animal);
 Dog *dog=new Dog;
 fun(dog);
 system("pause");
 return 0;
}

输出为:
animal is eating
dog is eating

有了虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态(Polymorphism)。

C++ 虚函数对于多态具有决定性的作用,有虚函数才能构成多态。

  1. 只需要在虚函数的声明处加上 virtual 关键字,类外函数定义处可以加也可以不加。

  2. 可以只将基类中的函数声明为虚函数,这样所有派生类中的同名函数都将自动成为虚函数。

  3. 当在基类中定义了虚函数时,如果派生类没有定义新的同名函数作为虚函数,那么将使用基类的虚函数。

  4. 只有派生类的虚函数与基类的虚函数函数原型相同,才能构成多态(通过基类指针访问派生类函数)

  5. 构造函数不能是虚函数。对于基类的构造函数,它仅仅是在派生类构造函数中被调用。

  6. 析构函数可以声明为虚函数,而且有时候必须要声明为虚函数。

三、纯虚函数和虚析构

1、纯虚函数

在C++中,可以将虚函数声明为纯虚函数:

virtual 返回值类型 函数名(形参)=0

纯虚函数没有函数体,只有函数声明,在虚函数声明的结尾加上=0,表明此函数为纯虚函数。
一个类中如果有了纯虚函数或纯虚析构,那么这个类就不能用来实例化对象,但是可以定义指针,这个类被定义为抽象类。

#include<iostream>
using namespace std;
class Animal
{
public:
  virtual void eat()=0;
};
class Dog:public Animal
{
public:
   void eat();
};
void Dog::eat()
{
 cout << "dog is eating" << endl;
}
void fun(Animal*animal)
{
 animal->eat();
}
int main()
{
 Animal *animal=new Dog;
 fun(animal);
 system("pause");
 return 0;
}

2、虚析构

父类指针指向子类对象时,比如上面的 Animal *animal=new Dog;delete父类指针,会调用父类指针析构,不会调用子类指针析构,所以当我们需要调用子类析构时(需要释放子类对象的空间)需要把父类析构函数前面加上virtual,变成虚析构,这样在释放父类指针时会调用子类的析构

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值