C++基础4:多态
多态
多态:
不同类型对象调同相同接口完成不同的行为
根据对象的实际类型不同,可以自动完成不同的行为,而仅仅通过一致的调用形式
关系:
没有封装就不能继承,没有继承就没有运行时的多态
绑定:
早绑定/overload | 晚绑定/override |
---|---|
函数和运算符重载 | 继承与虚函数 |
1、覆盖(重写override)与虚函数的使用
1.1 覆盖成立的三个条件
1、继承
2、子类覆盖(重写)父类虚函数
3、父类指针/引用指向子类
1.2 多态产生的效果
同样的调用语句实现不同的表现,框架的基石,设计模式的基础
1.3 虚函数定义规则
1、如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,有无const,那么即使加上virtual关键字,也是不会覆盖。
2、只有类的成员函数才能说明为虚函数,因为虚函数仅适合用于有继承关系的类对象,所以普通函数不能说明为虚函数
3、静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制与某个对象
4、内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义,但是在编译的时候系统仍然将它看做是非内联的。
5、构造函数不能是虚函数,因为构造的时候,对象还是一片未定型的空间,只有构造完成后,对象才是具体类的实例。
6、析构函数可以是虚函数,而且通常声明为虚函数
子类以new方式实例化,指针赋值给父类指针,delete父类指针时,只调用父类的析构函数,不调用子类的析构函数
#include <iostream>
using namespace std;
class A{
virtual void test(){}
};
class B:public A{
void test(){}
};
class C:public B{
void test(){}
};
class A{
virtual void test(){}
};
class B:public A{
};
class C:public B{
void test(){}
};
特例:
class A{
virtual A* test(){}
};
class B:public A{
B* test(){}
};
1.4 多态的实现原理分析
当类中声明虚函数时,编译器会在类中生成一个虚函数表(基类和派生类中各自都会生成一个)
虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是编译器自动生成和维护的
virtual函数会被编译器放入虚函数表中
存在虚函数时,每个对象当中都有一个指向虚函数表的指针(vptr指针)
1.5 纯虚函数
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加=0
class 类名{
virtual 返回值类型 函数(形参列表) = 0;
}
1.6 抽象类
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数所以不能定义抽象类的对象
1.7 重载覆盖的区别
No. | 重载 | 覆盖 |
---|---|---|
1 | 重载要求函数名相同,但是参数列表必须不同,返回值可以相同也可以不同 | 覆盖要求函数名、参数列表、返回值必须相同 |
2 | 在类中重载是同一个类中不同成员函数之间的关系 | 在类中覆盖是子类和基类之间不同成员函数之间的关系 |
3 | 重载函数的调用是根据参数列表决定 | 覆盖函数的调用是根据对象类型决定 |
4 | 重载函数是在编译时确定调用一个函数 | 覆盖函数是在执行确定调用某个函数 |
1.8 代码如何判断是否调用了覆盖函数
1.9 测验
(1)写出下列程序的执行结果,并分析结果
如果程序编译有错,分析原因,并写出解决方法
#include <iostream>
using namespace std;
class A{
public:
virtual void Func(){
cout << "A::Func()"<<endl;
}
void Func(int n){
cout << "A::Func(" << n<<")"<<endl;
}
};
class B:public A{
public:
using A::Func;
void Func(){
cout << "B::Func()" << endl;
}
};
int main(){
B b;
b.Func();
b.A::Func(1);
A a(b);
a.Func();
a.Func(2);
A c;
c = b;
c.Func();
c.Func(3);
A *pa = &b;
pa->Func();
pa->Func(4);
A& fa =b;
fa.Func();
fa.Func(5);
return 0;
}
输出结果:
B::Func()
A::Func(1)
A::Func()
A::Func(2)
A::Func()
A::Func(3)
B::Func()
A::Func(4)
B::Func()
A::Func(5)
(2)写出下列程序的执行结果,并分析结果
如果程序编译有错,分析原因,并写出解决方法
#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;
}
输出结果:
Base constuct
Member constuct
Derive constuct
Base destuct
(3)写出下列程序的执行结果,并分析结果
如果程序编译有错,分析原因,并写出解决方法
#include <iostream>
using namespace std;
class Base{
public:
virtual void Func()const{cout << "Base" << endl;}
};
class Derive:public Base{
public:
void Func() const {cout << "Derive" << endl;}
};
int main(){
Base *pB = new Derive;
pB->Func();
(*pB).Func();
}
运行结果:
Derive
Derive
(4)写出下列程序的执行结果,并分析结果
如果程序编译有错,分析原因,并写出解决方法
#include <iostream>
using namespace std;
class A{
public:
void Func(){
cout << "A::Func()" << endl;
}
};
class B:public A{
public:
virtual void Func(){
cout << "B::Func" <<endl;
}
};
class C:public B{
public:
virtual void Func(){
cout << "C::Func" << endl;
}
};
int main(){
A*a = new C;
a->Func();
}
运行结果:
A::Func()
(5)写出下列程序的执行结果,并分析结果
如果程序编译有错,分析原因,并写出解决方法
#include <iostream>
using namespace std;
class Base{
public:
friend ostream& operator <<(ostream &os,const Base &b){return os << "Base";}
};
class Derive:public Base{
public:
friend ostream& operator <<(ostream &os,const Derive &b){return os << "Derive";}
};
int main(){
Base* pB = new Derive;
cout << (*pB) <<endl;
}
运行结果:
Base
(6)双重转发
#include <iostream>
using namespace std;
class Base{
public:
virtual ostream &Put(ostream &os) const {return os << "Base";}
friend ostream &operator<<(ostream &os,const Base &b){ return b.Put(os);}
};
class Derive:public Base{
public:
ostream &Put(ostream &os) const {return os << "Derive";}
friend ostream &operator << (ostream &os,const Derive &b) {return b.Put(os);}
};
int main(){
Base *pB = new Derive;
cout << (*pB) << endl;
}
运行结果:
Derive
(7)写出下列执行结果
#include <iostream>
#include <vector>
using namespace std;
class Member{
public:
Member(){cout << __func__ << endl;}
~Member(){cout << __func__ <<endl;}
};
class Base{
public:
Base(){cout << __func__ << endl;}
~Base(){cout << __func__ << endl;}
};
class Derive:public Base{
Member m;
public:
Derive(){cout << __func__ <<endl;}
~Derive(){cout << __func__ <<endl;}
};
int main(){
Base *b = new Derive;
delete b;
}
运行结果:
Base
Member
Derive
~Base