如何理解C++的多态性和类型动态绑定?
2015-12-03 19:20
363 查看
一.动态类型和动态绑定
第一部分参考:/article/2031612.html1.对象的静态类型:对象声明时的类型,在编译期确定的
2.对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。
示例:
class B { } class C : public B { } class D : public B { } D* pD = new D();//pD的静态类型是它声明的类型D*,动态类型也是D* B* pB = pD;//pB的静态类型是它声明的类型B*,动态类型是pB所指向的对象pD的类型D* C* pC = new C(); pB = pC;//pB的动态类型是可以更改的,现在它的动态类型是C*
3.静态绑定:某特性(函数)依赖与对象的静态类型,在编译期确定。
4.动态绑定:某特性(函数)依赖于对象的动态类型,在运行期确定。
一般而言,只有虚函数使动态绑定的,依赖于对象的动态类型,非虚函数是静态绑定的依赖于对象的静态类型。
#include <iostream> using namespace std; class B { public: void DoSomething(){ std::cout << "B::DoSomething()" << endl; } virtual void vfun(){ std::cout << "B::vfun()" << endl; } }; class D : public B { public: void DoSomething(){ std::cout << "D::DoSomething()" << endl; } virtual void vfun(){ std::cout << "D::vfun()" << endl; } }; int main() { D* pd = new D(); B* pb = pd; pd->DoSomething(); //D::DoSomething() pb->DoSomething(); //B::DoSomething() pd->vfun(); //D::DoSomething() pb->vfun(); //D::DoSomething() return 0; }
注意:当虚函数中含有缺省的参数(默认参数时),虚函数时动态绑定的,依赖于对象的动态类型,但是缺省参数是静态的,依赖于对象的静态类型。示例:
#include <iostream> using namespace std; class Person { public: virtual void print(){ std::cout << "I'm a person" << endl; } }; class Chinese : public Person { public: virtual void print(){ std::cout << "I'm as Chinese" << endl; } }; class American : public Person { public: virtual void print(){ std::cout << "I'm as American" << endl; } }; //reference void printPerson(Person& person){ person.print(); } //pointer void printPerson(Person* p){ p->print(); } int main() { Person p; Chinese c; American a; printPerson(p); printPerson(c); printPerson(a); printPerson(&p); printPerson(&c); printPerson(&a); return 0; }
View Code
4.多态的实现:多态是由继承和虚函数实现的,因为虚函数是动态绑定的,依赖于调用对象(静态类型为基类的指针和引用)的动态类型,所以根据动态类型的不同,而导致操作不同,也就是多态性。
3.虚函数的实现:简单的说虚函数是通过虚函数表来实现的。
每个带有虚函数的类,都会有一个虚函数表(vtbl),表中的每一项记录它一个的虚函数的地址。实际上一个函数指针的数组。类的对象的最前面存储虚函数表的地址。
虚函数表在类的继承中也会继承和重写,当有重写发生时,就会产生多态性。
#include <iostream> using namespace std; class Person { public: virtual void print(){ std::cout << "I'm a person" << endl; } virtual void foo(){} }; class Chinese : public Person { public: virtual void print(){ std::cout << "I'm as Chinese" << endl; } virtual void foo2(){} }; class American : public Person { public: virtual void print(){ std::cout << "I'm as American" << endl; } }; //reference void printPerson(Person& person){ person.print(); } //pointer void printPerson(Person* p){ p->print(); } int main() { Person p; Chinese c; American a; printPerson(&p); printPerson(&c); printPerson(&a); return 0; }
Person 类的vtbl : Person::print()的地址,Person::foo()的地址
Chinese类的地址:Chinese::print()的地址,Person::foo()的地址,Person::foo1()的地址
American类的地址:American::print()的地址,Person::foo()的地址
三、总结
多态是C++的三大特性之一,非常重要,产生的条件是继承关系,基类中存在虚成员函数,派生类override(重写覆盖)基类的的虚成员函数,在代码上表现为基类对象的指针或引用调用虚成员函数,运行结果表现为实际调用各自派生类重写的函数。多态的核心虚成员函数是动态绑定的,即依赖于对象的动态类型。理解多态的难点是虚函数的实现机制,即虚函数表。
相关文章推荐
- HDOJ 1004 C语言版
- c_6: c语言字符串
- C语言数据类型笔记 by STP
- 【C语言】printf函数详解
- C语言基础(六)
- C++存储类型
- C++指针笔记
- c语言中的 puts gets
- C语言:使用malloc开辟一个3*4的二维数组,并将内容初始化为1-12.
- C++primer plus第六版课后编程练习答案13.4
- 设计模式C++实现:代理模式
- C++primer plus第六版课后编程练习答案13.3
- 2015杭电新生赛1007油菜花王国【并查集】【图论】
- 2015杭电新生赛1004质方数【打素数表】
- 2015杭电新生赛1002投币洗衣机【水模拟】
- C++primer plus第六版课后编程练习答案13.1
- 2015杭电新生赛1001搬砖【dfs】
- C语言跳转到指定地址执行
- 2015杭电新生赛1003玩骰子【大型模拟】
- C++ vector用法