虚继承解决同源继承二义性
1 | class A{ |
通过虚继承,可以确保同源继承,只有一份相同的代码:
1 | class A1 :virtual public A{ |
虚函数实现多态
动态多态:在程序运行期间,决定哪个函数被调用(类似于动态代理)
1,继承
2,父类引用或指针接收子类的对象实例
3,函数重写
静态多态:子类进行方法重载
在Java中,默认情况下,使用父类变量来接收子类实例就能够实现动态多态,但是,C++中,要实现
动态多态,我们必须显式的将父类函数声明为虚函数;
plane.h1
2
3
4
5
6
7
8
9#pragma once
class Plane{
public:
// 为了实现动态多态,必须声明为virtual类型
virtual void fly();
virtual void land();
};
plane.cpp1
2
3
4
5
6
7
8
9
10
11
12#include "plane.h"
#include <iostream>
using namespace std;
void Plane::fly(){
cout << "simple fly" << endl;
}
void Plane::land(){
cout << "simple land" << endl;
}
jet.h1
2
3
4
5
6
7
8
9
10
11
12
13#include "plane.h"
#include <iostream>
using namespace std;
class Jet :public Plane{
public:
void fly();
void land();
};
jet.cpp1
2
3
4
5
6
7
8
9
10
11
12#include "jet.h"
#include <iostream>
using namespace std;
void Jet::fly(){
cout << "jet fly" << endl;
}
void Jet::land(){
cout << "jet land" << endl;
}
dragon.h1
2
3
4
5
6
7
8
9#pragma once
#include "plane.h"
class Dragon :public Plane{
public:
void fly();
void land();
};
dragon.cpp1
2
3
4
5
6
7
8
9
10
11
12#include "dragon.h"
#include <iostream>
using namespace std;
void Dragon::fly(){
cout << "Dragon fly" << endl;
}
void Dragon::land(){
cout << "Dragon land" << endl;
}
1 | #include "plane.h" |
纯虚函数
1,有纯虚函数的类即抽象类
2,抽象类不能被实例化
3,子类继承抽象类,必须实现父类的纯虚函数,否则子类也是抽象类
作用:为了继承约束,对于子类具体实现是未知的。
纯虚函数在函数声明后面必须增加”=0”,这是与虚函数的区别:
拥有纯虚函数的类是抽象类,是不允许进行实例化的:1
2
3
4
5
6
7
8
9class Tet{
public:
virtual void myFun()=0;
};
void main(){
// 实例化将在编译期就报错
Tet t;
}
拥有虚函数的类和普通类并没有太大区别(除了实现多态),不管函数只是头文件声明,还是已经实现了
函数体,都能够被直接实例化。
1 | class Tet{ |
拥有纯虚函数的类即为抽象类,抽象类是允许有非纯虚函数的;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36class Shape{
public:
// 纯虚函数
// 必须等于0,否则会被解释为函数的头文件函数声明
virtual void sayArea() = 0;
// 和Java一样,抽象类中可以有已经实现的方法
void print(){
cout << "I am print" << endl;
}
};
class Circle :public Shape{
public:
Circle(int r){
this->r = r;
}
void sayArea(){
cout << "Circle Area" << endl;
}
private:
int r;
};
void main(){
// 纯虚函数不能被实例化
//Shape s;
//s.sayArea();
// 子类必须实现抽象父类的方法,才能够被实例化
Circle c(2);
c.sayArea();
system("pause");
}
只包含纯虚函数的类即接口
接口与抽象类,在语法上区别并不是很大,只是逻辑上的划分(C++),可以认为,接口就是只存在
纯虚函数的抽象类。
1 | // 可以认为是接口 |