一,多态的理论推导
1.类型兼容性原则
在上一节的C++中的继承中介绍了什么是类型兼容性原则。所谓的类型兼容性原则是指子类公有继承自父类时,包含了父类的所有属性和方法,因此父类所能完成的功能,使用子类也可以替代完成,子类是一种特殊的父类。所以可以使用子类对象初始化父类对象,可以用父类指针指向子类对象,可以用父类引用来引用子类对象。
2.函数的重写
函数的发生在类的继承过程中,所谓的函数的重写是指在继承中,子类定义了与父类函数原型相同的函数,即定义了和父类中一样的函数。
3.类型兼容性原则遇上函数的重写
# include<iostream> using namespace std; /* 定义父类 */ class Parent { public: /* 定义print函数 */ void print() { cout << "Parent print()函数" << endl; } }; /* 定义子类继承自父类,并重写父类的print函数 */ class Child :public Parent { public: /* 重写父类的print函数 */ void print() { cout << "Child print()函数" << endl; } }; int main() { Child c; /* 调用子类对象的print函数,打印子类的print函数 */ c.print(); /* 通过使用作用域操作符调用父类的print函数,打印父类的print函数 */ c.Parent::print(); /* 当我们使用类型兼容性原则的时候,发现调用的函数是父类的print函数,这是符合编译器规则的 */ Parent p1 = c; p1.print(); Parent * p2 = &c; p2->print(); Parent& p3 = c; p3.print(); return 0; }
输出结果:
4.类型兼容性原则遇上函数的重写的总结
5.静态联编和动态联编
6.类型兼容性原则和函数重写所带来的问题
7.针对上述问题的解决
针对上面的问题,C++提供了一套解决方案来实现上述我们的期望,通过使用virtual关键字来修饰被重写的函数后,即可以实现我们上述的问题。
8.多态的代码示例
# include<iostream> using namespace std; /* 定义父类 */ class Parent { public: /* 定义print函数,使用virtual关键字修饰 */ virtual void print() { cout << "Parent print()函数" << endl; } }; /* 定义子类继承自父类,并重写父类的print函数 */ class Child :public Parent { public: /* 重写父类的print函数 */ virtual void print() { cout << "Child print()函数" << endl; } }; int main() { Child c; /* 调用子类对象的print函数,打印子类的print函数 */ c.print(); /* 通过使用作用域操作符调用父类的print函数,打印父类的print函数 */ c.Parent::print(); /* 调用父类对象的函数发现当父类指针(引用)指向(引用)子类对象时,调用的是子类对象的函数,元素除外 */ Parent p1 = c; p1.print(); Parent * p2 = &c; p2->print(); Parent& p3 = c; p3.print(); return 0; }
输出结果:
9.多态案例的分析
10.多态成立的条件
二,多态的原理探究
1.多态原理基础知识
2.多态实现原理图示
3.多态原理说明
4.vptr指针的存在证明
# include<iostream> using namespace std; class Test1 { public: /* 虚函数 */ virtual void test() { cout << "vptr指针的存在证明" << endl; } }; class Test2 { public: /* 普通成员函数 */ void test() { cout << "vptr指针的存在证明" << endl; } }; int main() { Test1 t1; Test2 t2; cout << "Test1 sizeof = " << sizeof(t1) << endl; cout << "Test1 sizeof = " << sizeof(t2) << endl; return 0; }
输出结果:
我们发现含有虚函数的类的对象包含了4个字节,说明存在一个vptr指针,因为指针大小即4个字节。
5.vptr指针的创建时机
vptr指针是在对象构造函数结束之后才创建的,然后指向虚函数表。
三,虚析构函数
1.虚析构函数的作用
当我们在开发父类的时候,通常会把父类的析构函数声明为虚函数,因为在继承中,当我们delete释放内存的时候,子类的对象的析构函数不会去执行,我们需要将父类的析构函数显式的声明为虚函数才会让子类的析构函数去调用执行。
2.案例演示
# include<iostream> using namespace std; class MyParent { public: MyParent() { cout << "MyParent构造函数" << endl; } /* 父类的析构函数一般声明为虚析构函数 */ virtual~MyParent() { cout << "MyParent析构函数" << endl; } }; class MyChild:public MyParent { public: MyChild() { cout << "MyChild构造函数" << endl; } ~MyChild() { cout << "MyChild析构函数" << endl; } }; int main() { /* 如果删除父类的虚析构函数,则子类的析构函数不会被调用执行 */ MyParent * p = new MyChild; delete p; return 0; }
四,函数的重载和重写的区别
1.函数的重载
2.函数的重写
原文:http://www.cnblogs.com/metalsteel/p/6284336.html