最近在学习 C++,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习C++的童鞋们提供一份参考。
多态
多态条件
多态是在不同继承关系的类对象,去调同一函数,产生了不同的行为。
就是说,有一对继承关系的两个类,这两个类里面都有一个函数且名字、参数、返回值均相同,然后我们通过调用函数来实现不同类对象完成不同的事件。
多态成立条件:
- 必须存在继承
- 必须存在函数重写
- 要有基类指针指向子类对象
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 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; }
|
多态案例
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 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; }
|
重写重定义重载的区别
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 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指针存在
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 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"); }
|
纯虚函数
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 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"); }
|