最近在学习 C++,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习C++的童鞋们提供一份参考。
多态
多态条件
多态是在不同继承关系的类对象,去调同一函数,产生了不同的行为。
就是说,有一对继承关系的两个类,这两个类里面都有一个函数且名字、参数、返回值均相同,然后我们通过调用函数来实现不同类对象完成不同的事件。
多态成立条件:
- 必须存在继承
- 必须存在函数重写
- 要有基类指针指向子类对象
| 12
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 
 | #include <iostream>
 using namespace std;
 
 class Parent
 {
 public:
 
 Parent(int a = 0)
 {
 this->a = a;
 }
 virtual void Print()
 {
 cout << "父类:" << a << endl;
 }
 protected:
 private:
 int a;
 };
 
 class Child : public Parent
 {
 public:
 Child(int b = 0)
 {
 this->b = b;
 }
 virtual void Print()
 {
 cout << "子类:" << b << endl;
 }
 
 protected:
 private:
 int b;
 };
 
 
 void HowToPrint1(Parent *p)
 {
 p->Print();
 }
 
 void HowToPrint2(Parent &myp)
 {
 myp.Print();
 }
 int main()
 {
 Parent p1(1);
 Child c1(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 HowToPrint1(&p1);
 HowToPrint1(&c1);
 HowToPrint2(p1);
 HowToPrint2(c1);
 
 system("pause");
 return 0;
 }
 
 | 
多态案例

| 12
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 
 | #include <iostream>using namespace std;
 
 
 class DuckBase
 {
 public:
 virtual void Cry() = 0;
 };
 
 class SmallDuck : public DuckBase
 {
 void Cry()
 {
 cout << "我是一只小鸭子,嘎嘎嘎" << endl;
 }
 };
 
 class BigDuck : public SmallDuck
 {
 void Cry()
 {
 cout << "我是一只大鸭子,嘎嘎嘎" << endl;
 }
 };
 
 
 class WoodDuck : public BigDuck
 {
 void Cry()
 {
 cout << "我是一只木鸭子,嘎嘎嘎" << endl;
 }
 };
 
 void Cry(DuckBase *Duck)
 {
 Duck->Cry();
 }
 
 int main()
 {
 SmallDuck s;
 BigDuck b;
 WoodDuck w;
 Cry(&s);
 Cry(&w);
 Cry(&b);
 system("pause");
 return 0;
 }
 
 | 
重写重定义重载的区别
| 12
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 
 | #include <cstdlib>#include <iostream>
 
 using namespace std;
 
 class Parent01
 {
 public:
 Parent01()
 {
 cout<<"Parent01:printf()..do"<<endl;
 }
 public:
 void func()
 {
 cout<<"Parent01:void func()"<<endl;
 }
 
 void abcd()
 {
 cout<<"Parent01:void func()"<<endl;
 }
 
 virtual void func(int i)
 {
 cout<<"Parent:void func(int i)"<<endl;
 }
 
 virtual void func(int i, int j)
 {
 cout<<"Parent:void func(int i, int j)"<<endl;
 }
 };
 
 
 
 
 
 class Child01 : public Parent01
 {
 
 public:
 
 
 
 void abcd(int a, int b)
 {
 cout<<"Parent01:void func()"<<endl;
 }
 
 
 void func(int i, int j)
 {
 cout<<"Child:void func(int i, int j)"<<" "<<i + j<<endl;
 }
 
 
 void func(int i, int j, int k)
 {
 cout<<"Child:void func(int i, int j, int k)"<<" "<<i + j + k<<endl;
 }
 };
 
 void run01(Parent01* p)
 {
 p->func(1, 2);
 }
 
 int main()
 {
 Parent01 p;
 
 p.func();
 p.func(1);
 p.func(1, 2);
 
 
 Child01 c;
 
 
 c.Parent01::func();
 
 
 
 
 
 
 system("pause");
 return 0;
 }
 
 
 
 
 
 
 
 
 
 
 
 | 
函数重载:
- 函数重载必须在同一个类中
- 子类无法继承父类的函数,父类同名函数将被名称覆盖
- 重载是在编译期间根据参数类型和个数决定函数调用
函数重写:
- 必须发生在父类与子类之间
- 父类与子类中的函数必须有完全相同的类型
- 使用virtual声明之后能够产生多态(如果不适用virtual,那叫重定义)
- 多态是在运行期间根据具体对象的类型决定函数调用
多态实现原理
- 当类中声明虚函数时,编译器回在类中生成一个虚函数表
- 虚函数表是一个存储类成员函数指针的数据结构
- 虚函数表是由编译器自动生成和维护的
- virtual成员函数回被编译器放入虚函数表中
- 存在虚函数是,每个对象中都有一个纸箱虚函数表的指针(vptr指针)
vptr指针存在
| 12
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 
 | #include <iostream>using namespace std;
 
 class AA
 {
 public:
 AA()
 {
 ;
 }
 ~AA()
 {
 ;
 }
 
 void Print()
 {
 printf("我是爷爷\n");
 }
 private:
 protected:
 
 };
 
 class BB : public AA
 {
 public:
 BB()
 {
 ;
 }
 ~BB()
 {
 ;
 }
 void Print()
 {
 printf("我是爸爸\n");
 }
 
 };
 
 
 
 class CC : public BB
 {
 public:
 CC()
 {
 ;
 }
 ~CC()
 {
 ;
 };
 virtual void Print()
 {
 printf("我是孙子\n");
 }
 
 };
 
 
 void Print(AA *a)
 {
 a->Print();
 }
 
 
 void main()
 {
 AA a;
 BB b;
 CC c;
 Print(&a);
 Print(&b);
 Print(&c);
 printf("sizeof = %d\n", sizeof(AA));
 printf("sizeof = %d\n", sizeof(BB));
 printf("sizeof = %d\n", sizeof(CC));
 system("pause");
 }
 
 | 
纯虚函数
| 12
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 
 | #include <iostream>using namespace std;
 
 class figure
 {
 public:
 virtual int showarea() = 0;
 };
 
 class Tri : public figure
 {
 public:
 Tri(int a = 0, int b = 0)
 {
 this->a = a;
 this->b = b;
 }
 virtual int showarea()
 {
 cout << "三角形s" << a*b / 2 << endl;
 return 0;
 }
 private:
 int a;
 int b;
 };
 
 class Squre : public figure
 {
 public:
 Squre(int a = 0, int b = 0)
 {
 this->a = a;
 this->b = b;
 }
 virtual int showarea()
 {
 cout << "四边形s" << a*b << endl;
 return 0;
 }
 private:
 int a;
 int b;
 };
 
 void Print(figure *p)
 {
 p->showarea();
 }
 
 void main()
 {
 figure *pBase = NULL;
 Tri t(10, 2);
 Print(&t);
 
 Squre s(10,20);
 
 Print(&s);
 system("pause");
 }
 
 |