1概念
多态:不同类型对象调用相同接口完成不同的行为。
1.1覆盖(重写override)成立的三个条件
1.继承
2.子类覆盖(重写)父类虚函数
3.父类指针/引用指向子类
1.2虚函数定义规则:
- 如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,有无const. 那么即使加上了virtual关键字,也是不会覆盖。
- 只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
- 静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。
- 内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义,但是在编译的时候系统仍然将它看做是非内联的。
- 构造函数不能是虚函数,因为构造的时候,对象还是一片未定型的空间,只有构造完成后,对象才是具体类的实例。
- 析构函数可以是虚函数,而且通常声明为虚函数。
1.3多态的实现原理分析
当类中声明虚函数时,编译器会在类中生成一个虚函数表(基类和派生类中各自都会生成一个)
1.4虚函数表
- 虚函数表是一个存储类成员函数指针的数据结构
- 虚函数表是由编译器自动生成和维护的
- virtual函数会被编译器放入虚函数表中
- 存在虚函数时,每个对象当中都有一个指向虚函数表的指针(vptr指针)
1.5纯虚函数
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加=0
class 类名{
virtual 返回值类型 函数(形参列表) = 0;
}
1.6抽象类
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。
1.7重载覆盖的区别
重载 | 覆盖 |
---|---|
重载要求函数名相同,但是参数列表必须不同,返回值可以相同也可以不同。 | 覆盖要求函数名、参数列表、返回值必须相同 |
在类中重载是同一个类中不同成员函数之间的关系。 | 在类中覆盖则是子类和基类之间不同成员函数之间的关系。 |
重载函数的调用是根据参数列表决定 | 覆盖函数的调用是根据对象类型决定 |
重载函数是在编译时确定调用一个函数 | 覆盖函数是在执行时确定调用个函数。 |
1.8代码如何判断是否调用了覆盖函数
#include<iostream>
using namespace std;
class A{
public:
A(){
}
virtual ~A(){
}
virtual void Function()const{
cout<<"A::FUNC"<<endl;
}
void Function(int n)const{
cout<<"A::FUNC("<< n<<")"<<endl;
}
};
class B:public A{
public:
using A::Function;
B(){
}
~B(){
}
void Function()const{ //同名隐藏规则
cout<<"B::FUNC"<<endl;
A::Function();
}
};
int main(){
B b;
b.Function();//调用b的
//b.Function(1);//报错
//两种解决方法
//1.b.A::Function()
//2. using A::Function;
A*p=new B;//创建B A
//一般来说,类型决定成员调用;但是多态是对象决定成员的调用
//多态3点
//1:赋值规则
//2:父类有虚函数
//3:子类中有虚函数的实现
p->Function();//多态
delete p;
有个问题:因为p指针是A类型 所以delete后 只忻构A 而B不析构
//解决方法 :在A中 将析构函数变成虚函数
p=NULL;
//原则:如果一个类或者它的父类存在被继承和虚函数 那么必须定义虚析构
cout<<"---------------------------"<<endl;
//另一种多态的方法
A &r=b;
r.Function();
}
引用和指针相同的判断方式
1.9测验
#include <iostream>
using namespace std;
class Base{
public:
Base(){
cout << "Base constuct" << endl;
}
~Base(){
cout << "Base destuct" << endl;
}
};
class Member{
public:
Member(){
cout << "Member constuct" << endl;
}
~Member(){
cout << "Member destuct" << endl;
}
};
class Derive:public Base{
public:
Derive(){
cout << "Derive constuct" << endl;
}
~Derive(){
cout << "Derive destuct" << endl;
}
private:
Member m;
};
int main(){
Base* pD = new Derive;
delete pD;
}
答案
[root@foundation66 c++]# g++ 多态练习.cpp
[root@foundation66 c++]# ./a.out
Base constuct//先
Member constuct
Derive constuct
Base destuct//父类指针只会调用父类析构函数
来源:CSDN
作者:。。
链接:https://blog.csdn.net/weixin_45639955/article/details/104296216